home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / bin / ckbcomp < prev    next >
Encoding:
Text File  |  2013-01-05  |  144.2 KB  |  4,729 lines

  1. #!/usr/bin/perl
  2.  
  3. #     ckbcomp -- translate XKB layout to loadkeys or kbdcontrol format
  4. #     Copyright ┬⌐ 2005,2006 Anton Zinoviev <anton@lml.bas.bg>
  5.  
  6. #     This program is free software; you can redistribute it and/or modify
  7. #     it under the terms of the GNU General Public License as published by
  8. #     the Free Software Foundation; either version 2 of the License, or
  9. #     (at your option) any later version.
  10.  
  11. #     This program is distributed in the hope that it will be useful,
  12. #     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. #     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. #     GNU General Public License for more details.
  15.  
  16. #     If you have not received a copy of the GNU General Public License
  17. #     along with this program, write to the Free Software Foundation, Inc.,
  18. #     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20. use warnings 'all';
  21. use strict;
  22. use locale;
  23.  
  24. my $debug_flag = 1;
  25. sub debug {
  26.     if ($debug_flag) {
  27.     print STDERR "@_";
  28.     }
  29. }
  30.  
  31. sub warning {
  32.     print STDERR  "WARNING: @_";
  33. }
  34.  
  35. ########### ARGUMENTS ###############################################
  36.  
  37. my $charmap;
  38. my $acm;
  39.  
  40. my $verbosity = 0;
  41.  
  42. my $installdir=$0;
  43. $installdir =~ s|/[^/]*$||g;
  44. if ($installdir =~ m|/bin$|) {
  45.     $installdir =~ s|/bin$||;
  46. } else {
  47.     $installdir .= "/..";
  48. }
  49. if ( $installdir eq '' || ! -d "$installdir/bin") {
  50.     $installdir = '/usr';
  51. }
  52.  
  53. my @xdirs = ('/etc/console-setup/ckb',
  54.              "$installdir/etc/console-setup/ckb",
  55.          '/usr/local/share/X11/xkb',
  56.          '/usr/share/X11/xkb',
  57.          '/etc/X11/xkb');
  58.  
  59. my $keycodes;
  60. my $symbols;
  61.  
  62. my $rules;
  63. my $model;
  64. my @layouts;
  65. my @variants = ();
  66. my @options = ();
  67. my $compact = 0;
  68. my $backspace = '';
  69. my $freebsd = 0;
  70.  
  71. while (@ARGV) {
  72.     $_ = shift @ARGV;
  73.     if (s/^-//) {
  74.     if (/^charmap$/) {
  75.         if ($charmap) {
  76.         die "$0: No more than one -charmap option is allowed\n";
  77.         }
  78.         $charmap = $ARGV[0];
  79.         shift @ARGV;
  80.     } elsif (/^v(erbose)?$/) {
  81.         if ($verbosity) {
  82.         die "$0: No more than one -verbose option is allowed\n";
  83.         }
  84.         if ($ARGV[0] =~ /^[0-9]|10$/) {
  85.         $verbosity = $ARGV[0];
  86.         shift @ARGV;
  87.         } else {
  88.         $verbosity = 5;
  89.         }
  90.     } elsif (/^I(.*)$/) {
  91.         @xdirs = ($1, @xdirs);
  92.     } elsif (/^keycodes$/) {
  93.         if ($keycodes) {
  94.         die "$0: No more than one -keycodes option is allowed\n";
  95.         }
  96.         $keycodes = $ARGV[0];
  97.         shift @ARGV;
  98.     } elsif (/^symbols$/) {
  99.         if ($symbols) {
  100.         die "$0: No more than one -symbols option is allowed\n";
  101.         }
  102.         $symbols = $ARGV[0];
  103.         shift @ARGV;
  104.     } elsif (/^rules$/) {
  105.         if ($rules) {
  106.         die "$0: No more than one -rules option is allowed\n";
  107.         }
  108.         $rules = $ARGV[0];
  109.         shift @ARGV;
  110.     } elsif (/^model$/) {
  111.         if ($model) {
  112.         die "$0: No more than one -model option is allowed\n";
  113.         }
  114.         $model = $ARGV[0];
  115.         $model =~ s/[[:space:]]//g;
  116.         shift @ARGV;
  117.     } elsif (/^layout$/) {
  118.         if (@layouts) {
  119.         die "$0: No more than one -layout option is allowed\n";
  120.         }
  121.         $ARGV[0] =~ s/[[:space:]]//g;
  122.         @layouts = split (/,/, $ARGV[0], -1);
  123.         shift @ARGV;
  124.     } elsif (/^variant$/) {
  125.         if (@variants) {
  126.         die "$0: No more than one -variant option is allowed\n";
  127.         }
  128.         $ARGV[0] =~ s/[[:space:]]//g;
  129.         @variants = split (/,/, $ARGV[0], -1);
  130.         shift @ARGV;
  131.     } elsif (/^option$/) {
  132.         $ARGV[0] =~ s/[[:space:]]//g;
  133.         @options = (@options, split (/,/, $ARGV[0], -1));
  134.         shift @ARGV;
  135.     } elsif (/^help$|^-help$|^\?$/) {
  136.         print <<EOT;
  137. Usage: ckbcomp [args] [<layout> [<variant> [<option> ... ]]]
  138. Where legal args are:
  139. -?,-help            Print this message
  140. -charmap <name>     Specifies the encoding to use
  141. -I<dir>             Add <dir> to list of directories to be used
  142. -keycodes <name>    Specifies keycodes component name
  143. -symbols <name>     Specifies symbols component name
  144. -rules <name>       Name of rules file to use
  145. -model <name>       Specifies model used to choose component names
  146. -layout <name>      Specifies layout used to choose component names
  147. -variant <name>     Specifies layout variant used to choose component names
  148. -option <name>      Adds an option used to choose component names
  149. -v[erbose] [<lvl>]  Sets verbosity (1..10).  Higher values yield
  150.                     more messages
  151. -compact            Generate compact keymap
  152. -freebsd            Generate keymap for FreeBSD
  153. -backspace bs|del   Backspace is BS (^h) or DEL (^?)
  154. EOT
  155.             exit 0;
  156.     } elsif (/^compact$/) {
  157.         $compact = 1;
  158.     } elsif (/^freebsd$/) {
  159.         $freebsd = 1;
  160.     } elsif (/^backspace$/) {
  161.         $backspace = $ARGV[0];
  162.             if ($backspace ne 'del' && $backspace ne 'bs') {
  163.                 die "$0: Option -backspace accepts either del or bs\n";
  164.             }
  165.             shift @ARGV;
  166.     } else {
  167.         die "$0: Unknown option -$_\n";
  168.     }
  169.     } else {
  170.     if (! @layouts) {
  171.         $_ =~ s/[[:space:]]//g;
  172.         @layouts = split (/,/, $_, -1);
  173.         @layouts = ('us') if (! @layouts);
  174.     } elsif (! @variants) {
  175.         $_ =~ s/[[:space:]]//g;
  176.         @variants = split (/,/, $_, -1);
  177.         @variants = ('') if (! @variants);
  178.     } else {
  179.         $_ =~ s/[[:space:]]//g;
  180.         @options = (@options, split (/,/, $_, -1));
  181.     }
  182.     }
  183. }
  184.  
  185. $rules = 'xorg' if (! $rules);
  186. $model = 'pc104' if (! $model);
  187. $backspace = $freebsd ? 'bs' : 'del' if (! $backspace);
  188.  
  189. ########### GLOBAL VARIABLES #########################################
  190.  
  191. my %rules_variables = (); # The variables defined in the rules file
  192.  
  193. my $arch = 'at'; # The name of a mapping between X key codes and kernel
  194.                  # keycodes
  195.  
  196. my %acmtable; # Unicode -> legacy code (defined only when -charmap is given)
  197.  
  198. my $KEYMAP = ''; # This variable contains the generated keymap
  199.  
  200. my $broken_caps = 0; # In unicode mode Caps_Lock doesn't work for non-ASCII
  201.                      # letters.  1 = the keymap contains non-ascii letters.
  202.                      # See http://bugzilla.kernel.org/show_bug.cgi?id=7746#c21
  203.  
  204. my %keycodes_table; # x keysym -> x key code
  205. my %aliases;        # x keysym -> x keysym
  206.  
  207. my %symbols_table;   # x key code -> [[symbols for group0,...],
  208.                      #                [symbols for group1,...], ...]
  209. my %types_table;     # x key code -> key type (i.e. "TWO_LEVEL")
  210.  
  211. my $augment_method = 1;   # Constants for different XKB include methods
  212. my $override_method = 2;
  213. my $replace_method = 3;
  214. my $alternate_method = 4;
  215. my $ignore_method = 5;    # This is not a XKB method and means "don't include"
  216.  
  217. my $filename;       # The name of the currently read file
  218. my $stream = '';    # The contents of $filename that still has not been parsed
  219. my $method = $override_method; # The current method (by default "override")
  220. my $base_group = 0; # The base group to include in (for "symbols" files only)
  221.  
  222. my %kernel_modifiers = ( # Linux
  223.                          'Shift' => 0x01,
  224.                          'Shift_Lock' => 0x01,
  225.                          'AltGr' => 0x02,
  226.                          'AltGr_Lock' => 0x02,
  227.                          'Control' => 0x04,
  228.                          'Control_Lock' => 0x04,
  229.                          'Alt' => 0x08,
  230.                          'Alt_Lock' => 0x08,
  231.                          'ShiftL' => 0x10,
  232.                          'ShiftL_Lock' => 0x10,
  233.                          'ShiftR' => 0x20,
  234.                          'ShiftR_Lock' => 0x20,
  235.                          'CtrlL' => 0x40,
  236.                          'CtrlL_Lock' => 0x40,
  237.                          'CtrlR' => 0x80,
  238.                          'CtrlR_Lock' => 0x80,
  239.                          # FreeBSD
  240.                          'lshift' => 0x01,
  241.                          'rshift' => 0x01,
  242.                          'shifta' => 0x01, # is this correct ?
  243.                          'lshifta' => 0x01, # is this correct ?
  244.                          'rshifta' => 0x01, # is this correct ?
  245.                          'alt' => 0x02,
  246.                          'lalt' => 0x02,
  247.                          'ralt' => 0x02,
  248.                          'alta' => 0x02, # is this correct ?
  249.                          'lalta' => 0x02, # is this correct ?
  250.                          'ralta' => 0x02, # is this correct ?
  251.                          'ctrl' => 0x04,
  252.                          'lctrl' => 0x04,
  253.                          'rctrl' => 0x04,
  254.                          'ctrla' => 0x04, # is this correct ?
  255.                          'lctrla' => 0x04, # is this correct ?
  256.                          'rctrla' => 0x04, # is this correct ?
  257.                          'alock' => 0x10,
  258.                          'ashift' => 0x10,
  259.     );
  260.  
  261. my @modifier_combinations = ('plain',
  262.                              'shift',
  263.                              'altgr',
  264.                              'altgr shift',
  265.                              'control',
  266.                              'control shift',
  267.                              'control altgr',
  268.                              'control altgr shift',
  269.                              'alt',
  270.                              'alt shift',
  271.                              'alt altgr',
  272.                              'alt altgr shift',
  273.                              'alt control',
  274.                              'alt control shift',
  275.                              'alt control altgr',
  276.                              'alt control altgr shift',
  277.                              'shiftl',
  278.                              'shiftl shift',
  279.                              'shiftl altgr',
  280.                              'shiftl altgr shift',
  281.                              'shiftl control',
  282.                              'shiftl control shift',
  283.                              'shiftl control altgr',
  284.                              'shiftl control altgr shift',
  285.                              'shiftl alt',
  286.                              'shiftl alt shift',
  287.                              'shiftl alt altgr',
  288.                              'shiftl alt altgr shift',
  289.                              'shiftl alt control',
  290.                              'shiftl alt control shift',
  291.                              'shiftl alt control altgr',
  292.                              'shiftl alt control altgr shift',
  293.                              'shiftr',
  294.                              'shiftr shift',
  295.                              'shiftr altgr',
  296.                              'shiftr altgr shift',
  297.                              'shiftr control',
  298.                              'shiftr control shift',
  299.                              'shiftr control altgr',
  300.                              'shiftr control altgr shift',
  301.                              'shiftr alt',
  302.                              'shiftr alt shift',
  303.                              'shiftr alt altgr',
  304.                              'shiftr alt altgr shift',
  305.                              'shiftr alt control',
  306.                              'shiftr alt control shift',
  307.                              'shiftr alt control altgr',
  308.                              'shiftr alt control altgr shift',
  309.                              'shiftr shiftl',
  310.                              'shiftr shiftl shift',
  311.                              'shiftr shiftl altgr',
  312.                              'shiftr shiftl altgr shift',
  313.                              'shiftr shiftl control',
  314.                              'shiftr shiftl control shift',
  315.                              'shiftr shiftl control altgr',
  316.                              'shiftr shiftl control altgr shift',
  317.                              'shiftr shiftl alt',
  318.                              'shiftr shiftl alt shift',
  319.                              'shiftr shiftl alt altgr',
  320.                              'shiftr shiftl alt altgr shift',
  321.                              'shiftr shiftl alt control',
  322.                              'shiftr shiftl alt control shift',
  323.                              'shiftr shiftl alt control altgr',
  324.                              'shiftr shiftl alt control altgr shift',
  325.                              'ctrll',
  326.                              'ctrll shift',
  327.                              'ctrll altgr',
  328.                              'ctrll altgr shift',
  329.                              'ctrll control',
  330.                              'ctrll control shift',
  331.                              'ctrll control altgr',
  332.                              'ctrll control altgr shift',
  333.                              'ctrll alt',
  334.                              'ctrll alt shift',
  335.                              'ctrll alt altgr',
  336.                              'ctrll alt altgr shift',
  337.                              'ctrll alt control',
  338.                              'ctrll alt control shift',
  339.                              'ctrll alt control altgr',
  340.                              'ctrll alt control altgr shift',
  341.                              'ctrll shiftl',
  342.                              'ctrll shiftl shift',
  343.                              'ctrll shiftl altgr',
  344.                              'ctrll shiftl altgr shift',
  345.                              'ctrll shiftl control',
  346.                              'ctrll shiftl control shift',
  347.                              'ctrll shiftl control altgr',
  348.                              'ctrll shiftl control altgr shift',
  349.                              'ctrll shiftl alt',
  350.                              'ctrll shiftl alt shift',
  351.                              'ctrll shiftl alt altgr',
  352.                              'ctrll shiftl alt altgr shift',
  353.                              'ctrll shiftl alt control',
  354.                              'ctrll shiftl alt control shift',
  355.                              'ctrll shiftl alt control altgr',
  356.                              'ctrll shiftl alt control altgr shift',
  357.                              'ctrll shiftr',
  358.                              'ctrll shiftr shift',
  359.                              'ctrll shiftr altgr',
  360.                              'ctrll shiftr altgr shift',
  361.                              'ctrll shiftr control',
  362.                              'ctrll shiftr control shift',
  363.                              'ctrll shiftr control altgr',
  364.                              'ctrll shiftr control altgr shift',
  365.                              'ctrll shiftr alt',
  366.                              'ctrll shiftr alt shift',
  367.                              'ctrll shiftr alt altgr',
  368.                              'ctrll shiftr alt altgr shift',
  369.                              'ctrll shiftr alt control',
  370.                              'ctrll shiftr alt control shift',
  371.                              'ctrll shiftr alt control altgr',
  372.                              'ctrll shiftr alt control altgr shift',
  373.                              'ctrll shiftr shiftl',
  374.                              'ctrll shiftr shiftl shift',
  375.                              'ctrll shiftr shiftl altgr',
  376.                              'ctrll shiftr shiftl altgr shift',
  377.                              'ctrll shiftr shiftl control',
  378.                              'ctrll shiftr shiftl control shift',
  379.                              'ctrll shiftr shiftl control altgr',
  380.                              'ctrll shiftr shiftl control altgr shift',
  381.                              'ctrll shiftr shiftl alt',
  382.                              'ctrll shiftr shiftl alt shift',
  383.                              'ctrll shiftr shiftl alt altgr',
  384.                              'ctrll shiftr shiftl alt altgr shift',
  385.                              'ctrll shiftr shiftl alt control',
  386.                              'ctrll shiftr shiftl alt control shift',
  387.                              'ctrll shiftr shiftl alt control altgr',
  388.                              'ctrll shiftr shiftl alt control altgr shift',
  389.                 );
  390.  
  391. # Some Unicodes cause the kernel/loadkeys to issue "Segmentation fault"
  392. # kbd 1.15-1 (deliberately) fails on anything in the range 0xf000..0xffff;
  393. # see http://bugs.debian.org/500116.
  394. my %forbidden;
  395. {
  396.     for my $i (0xf000..0xffff) {
  397.     $forbidden{$i} = 1;
  398.     }
  399. }
  400.  
  401. my %xkbsym_table = (
  402.     'space' => '0020',
  403.     'exclam' => '0021',
  404.     'quotedbl' => '0022',
  405.     'numbersign' => '0023',
  406.     'dollar' => '0024',
  407.     'percent' => '0025',
  408.     'ampersand' => '0026',
  409.     'apostrophe' => '0027',
  410.     'quoteright' => '0027',
  411.     'parenleft' => '0028',
  412.     'parenlef' => '0028', # Is this recognised by X ? (speling error)
  413.     'parenright' => '0029',
  414.     'asterisk' => '002a',
  415.     'asterix' => '002a', # Is this recognised by X ? (speling error)
  416.     'plus' => '002b',
  417.     'comma' => '002c',
  418.     'minus' => '002d',
  419.     'period' => '002e',
  420.     'slash' => '002f',
  421.     '0' => '0030',
  422.     '1' => '0031',
  423.     '2' => '0032',
  424.     '3' => '0033',
  425.     '4' => '0034',
  426.     '5' => '0035',
  427.     '6' => '0036',
  428.     '7' => '0037',
  429.     '8' => '0038',
  430.     '9' => '0039',
  431.     'colon' => '003a',
  432.     'semicolon' => '003b',
  433.     'less' => '003c',
  434.     'equal' => '003d',
  435.     'greater' => '003e',
  436.     'question' => '003f',
  437.     'at' => '0040',
  438.     'A' => '0041',
  439.     'B' => '0042',
  440.     'C' => '0043',
  441.     'D' => '0044',
  442.     'E' => '0045',
  443.     'F' => '0046',
  444.     'G' => '0047',
  445.     'H' => '0048',
  446.     'I' => '0049',
  447.     'J' => '004a',
  448.     'K' => '004b',
  449.     'L' => '004c',
  450.     'M' => '004d',
  451.     'N' => '004e',
  452.     'O' => '004f',
  453.     'P' => '0050',
  454.     'Q' => '0051',
  455.     'R' => '0052',
  456.     'S' => '0053',
  457.     'T' => '0054',
  458.     'U' => '0055',
  459.     'V' => '0056',
  460.     'W' => '0057',
  461.     'X' => '0058',
  462.     'Y' => '0059',
  463.     'Z' => '005a',
  464.     'bracketleft' => '005b',
  465.     'backslash' => '005c',
  466.     'backlash' => '005c',   # Is this recognised by X ? (speling error)
  467.     'bracketright' => '005d',
  468.     'circumflex' => '005e',
  469.     'asciicircum' => '005e',
  470.     'underscore' => '005f',
  471.     'grave' => '0060',
  472.     'quoteleft' => '0060',
  473.     'a' => '0061',
  474.     'b' => '0062',
  475.     'c' => '0063',
  476.     'd' => '0064',
  477.     'e' => '0065',
  478.     'f' => '0066',
  479.     'g' => '0067',
  480.     'h' => '0068',
  481.     'i' => '0069',
  482.     'j' => '006a',
  483.     'k' => '006b',
  484.     'l' => '006c',
  485.     'm' => '006d',
  486.     'n' => '006e',
  487.     'o' => '006f',
  488.     'p' => '0070',
  489.     'q' => '0071',
  490.     'r' => '0072',
  491.     's' => '0073',
  492.     't' => '0074',
  493.     'u' => '0075',
  494.     'v' => '0076',
  495.     'w' => '0077',
  496.     'x' => '0078',
  497.     'y' => '0079',
  498.     'z' => '007a',
  499.     'braceleft' => '007b',
  500.     'pipe' => '007c', # Is this recognised by X ?
  501.     'bar' => '007c',
  502.     'braceright' => '007d',
  503.     'asciitilde' => '007e',
  504.     'nobreakspace' => '00a0',
  505.     'exclamdown' => '00a1',
  506.     'cent' => '00a2',
  507.     'sterling' => '00a3',
  508.     'currency' => '00a4',
  509.     'yen' => '00a5',
  510.     'brokenbar' => '00a6',
  511.     'section' => '00a7',
  512.     'diaeresis' => '00a8',
  513.     'copyright' => '00a9',
  514.     'ordfeminine' => '00aa',
  515.     'guillemotleft' => '00ab',
  516.     'notsign' => '00ac',
  517.     'hyphen' => '00ad',
  518.     'registered' => '00ae',
  519.     'macron' => '00af',
  520.     'overbar' => '00af',
  521.     'degree' => '00b0',
  522.     'plusminus' => '00b1',
  523.     'twosuperior' => '00b2',
  524.     'threesuperior' => '00b3',
  525.     'acute' => '0027', # APOSTROPHE instead of ACUTE ACCENT
  526.     'mu' => '00b5',
  527.     'paragraph' => '00b6',
  528.     'periodcentered' => '00b7',
  529.     'cedilla' => '00b8',
  530.     'onesuperior' => '00b9',
  531.     'masculine' => '00ba',
  532.     'guillemotright' => '00bb',
  533.     'onequarter' => '00bc',
  534.     'onehalf' => '00bd',
  535.     'threequarters' => '00be',
  536.     'questiondown' => '00bf',
  537.     'Agrave' => '00c0',
  538.     'Aacute' => '00c1',
  539.     'Acircumflex' => '00c2',
  540.     'Atilde' => '00c3',
  541.     'Adiaeresis' => '00c4',
  542.     'Aring' => '00c5',
  543.     'AE' => '00c6',
  544.     'Ccedilla' => '00c7',
  545.     'Egrave' => '00c8',
  546.     'Eacute' => '00c9',
  547.     'Ecircumflex' => '00ca',
  548.     'Ediaeresis' => '00cb',
  549.     'Igrave' => '00cc',
  550.     'Iacute' => '00cd',
  551.     'Icircumflex' => '00ce',
  552.     'Idiaeresis' => '00cf',
  553.     'ETH' => '00d0',
  554.     'Eth' => '00d0',
  555.     'Ntilde' => '00d1',
  556.     'Ograve' => '00d2',
  557.     'Oacute' => '00d3',
  558.     'Ocircumflex' => '00d4',
  559.     'Otilde' => '00d5',
  560.     'Odiaeresis' => '00d6',
  561.     'multiply' => '00d7',
  562.     'Ooblique' => '00d8',
  563.     'Oslash' => '00d8',
  564.     'Ugrave' => '00d9',
  565.     'Uacute' => '00da',
  566.     'Ucircumflex' => '00db',
  567.     'Udiaeresis' => '00dc',
  568.     'Yacute' => '00dd',
  569.     'THORN' => '00de',
  570.     'Thorn' => '00de',
  571.     'ssharp' => '00df',
  572.     'agrave' => '00e0',
  573.     'aacute' => '00e1',
  574.     'acircumflex' => '00e2',
  575.     'atilde' => '00e3',
  576.     'adiaeresis' => '00e4',
  577.     'aring' => '00e5',
  578.     'ae' => '00e6',
  579.     'ccedilla' => '00e7',
  580.     'egrave' => '00e8',
  581.     'eacute' => '00e9',
  582.     'ecircumflex' => '00ea',
  583.     'ediaeresis' => '00eb',
  584.     'igrave' => '00ec',
  585.     'iacute' => '00ed',
  586.     'icircumflex' => '00ee',
  587.     'idiaeresis' => '00ef',
  588.     'eth' => '00f0',
  589.     'ntilde' => '00f1',
  590.     'ograve' => '00f2',
  591.     'oacute' => '00f3',
  592.     'ocircumflex' => '00f4',
  593.     'otilde' => '00f5',
  594.     'odiaeresis' => '00f6',
  595.     'division' => '00f7',
  596.     'oslash' => '00f8',
  597.     'ooblique' => '00f8',
  598.     'ugrave' => '00f9',
  599.     'uacute' => '00fa',
  600.     'ucircumflex' => '00fb',
  601.     'udiaeresis' => '00fc',
  602.     'yacute' => '00fd',
  603.     'thorn' => '00fe',
  604.     'ydiaeresis' => '00ff',
  605.     'Amacron' => '0100',
  606.     'amacron' => '0101',
  607.     'Abreve' => '0102',
  608.     'abreve' => '0103',
  609.     'Aogonek' => '0104',
  610.     'aogonek' => '0105',
  611.     'Cacute' => '0106',
  612.     'cacute' => '0107',
  613.     'Ccircumflex' => '0108',
  614.     'ccircumflex' => '0109',
  615.     'Cabovedot' => '010a',
  616.     'cabovedot' => '010b',
  617.     'Ccaron' => '010c',
  618.     'ccaron' => '010d',
  619.     'Dcaron' => '010e',
  620.     'dcaron' => '010f',
  621.     'Dstroke' => '0110',
  622.     'dstroke' => '0111',
  623.     'Emacron' => '0112',
  624.     'emacron' => '0113',
  625.     'Eabovedot' => '0116',
  626.     'eabovedot' => '0117',
  627.     'Eogonek' => '0118',
  628.     'eogonek' => '0119',
  629.     'Ecaron' => '011a',
  630.     'ecaron' => '011b',
  631.     'Gcircumflex' => '011c',
  632.     'gcircumflex' => '011d',
  633.     'Gbreve' => '011e',
  634.     'gbreve' => '011f',
  635.     'Gabovedot' => '0120',
  636.     'gabovedot' => '0121',
  637.     'Gcedilla' => '0122',
  638.     'gcedilla' => '0123',
  639.     'Hcircumflex' => '0124',
  640.     'hcircumflex' => '0125',
  641.     'Hstroke' => '0126',
  642.     'hstroke' => '0127',
  643.     'Itilde' => '0128',
  644.     'itilde' => '0129',
  645.     'Imacron' => '012a',
  646.     'imacron' => '012b',
  647.     'Ibreve' => '012c',
  648.     'ibreve' => '012d',
  649.     'Iogonek' => '012e',
  650.     'iogonek' => '012f',
  651.     'Iabovedot' => '0130',
  652.     'idotless' => '0131',
  653.     'Jcircumflex' => '0134',
  654.     'jcircumflex' => '0135',
  655.     'Kcedilla' => '0136',
  656.     'kcedilla' => '0137',
  657.     'kra' => '0138',
  658.     'Lacute' => '0139',
  659.     'lacute' => '013a',
  660.     'Lcedilla' => '013b',
  661.     'lcedilla' => '013c',
  662.     'Lcaron' => '013d',
  663.     'lcaron' => '013e',
  664.     'Lstroke' => '0141',
  665.     'lstroke' => '0142',
  666.     'Nacute' => '0143',
  667.     'nacute' => '0144',
  668.     'Ncedilla' => '0145',
  669.     'ncedilla' => '0146',
  670.     'Ncaron' => '0147',
  671.     'ncaron' => '0148',
  672.     'ENG' => '014a',
  673.     'eng' => '014b',
  674.     'Omacron' => '014c',
  675.     'omacron' => '014d',
  676.     'Odoubleacute' => '0150',
  677.     'odoubleacute' => '0151',
  678.     'OE' => '0152',
  679.     'oe' => '0153',
  680.     'Racute' => '0154',
  681.     'racute' => '0155',
  682.     'Rcedilla' => '0156',
  683.     'rcedilla' => '0157',
  684.     'Rcaron' => '0158',
  685.     'rcaron' => '0159',
  686.     'Sacute' => '015a',
  687.     'sacute' => '015b',
  688.     'Scircumflex' => '015c',
  689.     'scircumflex' => '015d',
  690.     'Scedilla' => '015e',
  691.     'scedilla' => '015f',
  692.     'Scaron' => '0160',
  693.     'scaron' => '0161',
  694.     'Tcedilla' => '0162',
  695.     'tcedilla' => '0163',
  696.     'Tcaron' => '0164',
  697.     'tcaron' => '0165',
  698.     'Tslash' => '0166',
  699.     'tslash' => '0167',
  700.     'Utilde' => '0168',
  701.     'utilde' => '0169',
  702.     'Umacron' => '016a',
  703.     'umacron' => '016b',
  704.     'Ubreve' => '016c',
  705.     'ubreve' => '016d',
  706.     'Uring' => '016e',
  707.     'uring' => '016f',
  708.     'Udoubleacute' => '0170',
  709.     'udoubleacute' => '0171',
  710.     'Uogonek' => '0172',
  711.     'uogonek' => '0173',
  712.     'Wcircumflex' => '0174',
  713.     'wcircumflex' => '0175',
  714.     'Ycircumflex' => '0176',
  715.     'ycircumflex' => '0177',
  716.     'Ydiaeresis' => '0178',
  717.     'Zacute' => '0179',
  718.     'zacute' => '017a',
  719.     'Zabovedot' => '017b',
  720.     'zabovedot' => '017c',
  721.     'Zcaron' => '017d',
  722.     'zcaron' => '017e',
  723.     'SCHWA' => '018f',
  724.     'Schwa' => '018f', # Is this recognised by X ?
  725.     'function' => '0192',
  726.     'Obarred' => '019f',
  727.     'Ohorn' => '01a0', # Is this recognised by X ?
  728.     'ohorn' => '01a1', # Is this recognised by X ?
  729.     'Uhorn' => '01af',
  730.     'uhorn' => '01b0',
  731.     'Zstroke' => '01b5',
  732.     'zstroke' => '01b6',
  733.     'Ocaron' => '01d1',
  734.     'ocaron' => '01d2',
  735.     'Gcaron' => '01e6', # Is this recognised by X ?
  736.     'gcaron' => '01e7', # Is this recognised by X ?
  737.     'schwa' => '0259', # Is this recognised by X ?
  738.     'obarred' => '0275',
  739.     'caron' => '02c7',
  740.     'breve' => '02d8',
  741.     'abovedot' => '02d9',
  742.     'ogonek' => '02db',
  743.     'doubleacute' => '02dd',
  744.     'Greek_accentdieresis' => '0385',
  745.     'Greek_ALPHAaccent' => '0386',
  746.     'Greek_EPSILONaccent' => '0388',
  747.     'Greek_ETAaccent' => '0389',
  748.     'Greek_IOTAaccent' => '038a',
  749.     'Greek_OMICRONaccent' => '038c',
  750.     'Greek_UPSILONaccent' => '038e',
  751.     'Greek_OMEGAaccent' => '038f',
  752.     'Greek_iotaaccentdieresis' => '0390',
  753.     'Greek_ALPHA' => '0391',
  754.     'Greek_BETA' => '0392',
  755.     'Greek_GAMMA' => '0393',
  756.     'Greek_DELTA' => '0394',
  757.     'Greek_EPSILON' => '0395',
  758.     'Greek_ZETA' => '0396',
  759.     'Greek_ETA' => '0397',
  760.     'Greek_THETA' => '0398',
  761.     'Greek_IOTA' => '0399',
  762.     'Greek_KAPPA' => '039a',
  763.     'Greek_LAMBDA' => '039b',
  764.     'Greek_LAMDA' => '039b',   # Is this recognised by X ? (speling error)
  765.     'Greek_MU' => '039c',
  766.     'Greek_NU' => '039d',
  767.     'Greek_XI' => '039e',
  768.     'Greek_OMICRON' => '039f',
  769.     'Greek_PI' => '03a0',
  770.     'Greek_RHO' => '03a1',
  771.     'Greek_SIGMA' => '03a3',
  772.     'Greek_TAU' => '03a4',
  773.     'Greek_UPSILON' => '03a5',
  774.     'Greek_PHI' => '03a6',
  775.     'Greek_CHI' => '03a7',
  776.     'Greek_PSI' => '03a8',
  777.     'Greek_OMEGA' => '03a9',
  778.     'Greek_IOTAdiaeresis' => '03aa',
  779.     'Greek_UPSILONdieresis' => '03ab',
  780.     'Greek_alphaaccent' => '03ac',
  781.     'Greek_epsilonaccent' => '03ad',
  782.     'Greek_etaaccent' => '03ae',
  783.     'Greek_iotaaccent' => '03af',
  784.     'Greek_upsilonaccentdieresis' => '03b0',
  785.     'Greek_alpha' => '03b1',
  786.     'Greek_beta' => '03b2',
  787.     'Greek_gamma' => '03b3',
  788.     'Greek_delta' => '03b4',
  789.     'Greek_epsilon' => '03b5',
  790.     'Greek_zeta' => '03b6',
  791.     'Greek_eta' => '03b7',
  792.     'Greek_theta' => '03b8',
  793.     'Greek_iota' => '03b9',
  794.     'Greek_kappa' => '03ba',
  795.     'Greek_lambda' => '03bb',
  796.     'Greek_lamda' => '03bb', # Is this recognised by X ? (speling error)
  797.     'Greek_mu' => '03bc',
  798.     'Greek_nu' => '03bd',
  799.     'Greek_xi' => '03be',
  800.     'Greek_omicron' => '03bf',
  801.     'Greek_pi' => '03c0',
  802.     'Greek_rho' => '03c1',
  803.     'Greek_finalsmallsigma' => '03c2',
  804.     'Greek_sigma' => '03c3',
  805.     'Greek_tau' => '03c4',
  806.     'Greek_upsilon' => '03c5',
  807.     'Greek_phi' => '03c6',
  808.     'Greek_chi' => '03c7',
  809.     'Greek_psi' => '03c8',
  810.     'Greek_omega' => '03c9',
  811.     'Greek_iotadieresis' => '03ca',
  812.     'Greek_upsilondieresis' => '03cb',
  813.     'Greek_omicronaccent' => '03cc',
  814.     'Greek_upsilonaccent' => '03cd',
  815.     'Greek_omegaaccent' => '03ce',
  816.     'Cyrillic_IO' => '0401',
  817.     'Serbian_DJE' => '0402',
  818.     'Macedonia_GJE' => '0403',
  819.     'Ukrainian_IE' => '0404',
  820.     'Macedonia_DSE' => '0405',
  821.     'Ukrainian_I' => '0406',
  822.     'Ukrainian_YI' => '0407',
  823.     'Cyrillic_JE' => '0408',
  824.     'Cyrillic_LJE' => '0409',
  825.     'Cyrillic_NJE' => '040a',
  826.     'Serbian_TSHE' => '040b',
  827.     'Macedonia_KJE' => '040c',
  828.     'Byelorussian_SHORTU' => '040e',
  829.     'Cyrillic_DZHE' => '040f',
  830.     'Cyrillic_A' => '0410',
  831.     'Cyrillic_BE' => '0411',
  832.     'Cyrillic_VE' => '0412',
  833.     'Cyrillic_GHE' => '0413',
  834.     'Cyrillic_DE' => '0414',
  835.     'Cyrillic_IE' => '0415',
  836.     'Cyrillic_ZHE' => '0416',
  837.     'Cyrillic_ZH' => '0416',
  838.     'Cyrillic_ZE' => '0417',
  839.     'Cyrillic_I' => '0418',
  840.     'Cyrillic_SHORTI' => '0419',
  841.     'Cyrillic_KA' => '041a',
  842.     'Cyrillic_EL' => '041b',
  843.     'Cyrillic_EM' => '041c',
  844.     'Cyrillic_EN' => '041d',
  845.     'Cyrillic_N' => '041d',
  846.     'Cyrillic_O' => '041e',
  847.     'Cyrillic_PE' => '041f',
  848.     'Cyrillic_ER' => '0420',
  849.     'Cyrillic_ES' => '0421',
  850.     'Cyrillic_TE' => '0422',
  851.     'Cyrillic_U' => '0423',
  852.     'Cyrillic_EF' => '0424',
  853.     'Cyrillic_F' => '0424',
  854.     'Cyrillic_HA' => '0425',
  855.     'Cyrillic_TSE' => '0426',
  856.     'Cyrillic_CHE' => '0427',
  857.     'Cyrillic_SHA' => '0428',
  858.     'Cyrillic_SHCHA' => '0429',
  859.     'Cyrillic_HARDSIGN' => '042a',
  860.     'Cyrillic_YERU' => '042b',
  861.     'Cyrillic_UI' => '042b',
  862.     'Cyrillic_SOFTSIGN' => '042c',
  863.     'Cyrillic_E' => '042d',
  864.     'Cyrillic_YU' => '042e',
  865.     'Cyrillic_YA' => '042f',
  866.     'Cyrillic_a' => '0430',
  867.     'Cyrillic_be' => '0431',
  868.     'Cyrillic_ve' => '0432',
  869.     'Cyrillic_ghe' => '0433',
  870.     'Cyrillic_de' => '0434',
  871.     'Cyrillic_ie' => '0435',
  872.     'Cyrillic_zhe' => '0436',
  873.     'Cyrillic_zh' => '0436',
  874.     'Cyrillic_ze' => '0437',
  875.     'Cyrillic_i' => '0438',
  876.     'Cyrillic_shorti' => '0439',
  877.     'Cyrillic_ka' => '043a',
  878.     'Cyrillic_el' => '043b',
  879.     'Cyrillic_em' => '043c',
  880.     'Cyrillic_en' => '043d',
  881.     'Cyrillic_n' => '043d',
  882.     'Cyrillic_o' => '043e',
  883.     'Cyrillic_pe' => '043f',
  884.     'Cyrillic_er' => '0440',
  885.     'Cyrillic_es' => '0441',
  886.     'Cyrillic_te' => '0442',
  887.     'Cyrillic_u' => '0443',
  888.     'Cyrillic_ef' => '0444',
  889.     'Cyrillic_f' => '0444',
  890.     'Cyrillic_ha' => '0445',
  891.     'Cyrillic_tse' => '0446',
  892.     'Cyrillic_che' => '0447',
  893.     'Cyrillic_sha' => '0448',
  894.     'Cyrillic_shcha' => '0449',
  895.     'Cyrillic_hardsign' => '044a',
  896.     'Cyrillic_yeru' => '044b',
  897.     'Cyrillic_ui' => '044b',
  898.     'Cyrillic_softsign' => '044c',
  899.     'Cyrillic_e' => '044d',
  900.     'Cyrillic_yu' => '044e',
  901.     'Cyrillic_ya' => '044f',
  902.     'Cyrillic_io' => '0451',
  903.     'Serbian_dje' => '0452',
  904.     'Macedonia_gje' => '0453',
  905.     'Ukrainian_ie' => '0454',
  906.     'Macedonia_dse' => '0455',
  907.     'Ukrainian_i' => '0456',
  908.     'Ukrainian_yi' => '0457',
  909.     'Cyrillic_je' => '0458',
  910.     'Cyrillic_lje' => '0459',
  911.     'Cyrillic_nje' => '045a',
  912.     'Serbian_tshe' => '045b',
  913.     'Macedonia_kje' => '045c',
  914.     'Byelorussian_shortu' => '045e',
  915.     'Cyrillic_dzhe' => '045f',
  916.     'Ukrainian_GHE_WITH_UPTURN' => '0490', # Is this recognised by X ?
  917.     'Ukrainian_ghe_with_upturn' => '0491', # Is this recognised by X ?
  918.     'Cyrillic_GHE_bar' => '0492', # Is this recognised by X ?
  919.     'Cyrillic_ghe_bar' => '0493', # Is this recognised by X ?
  920.     'Cyrillic_ZHE_descender' => '0496',
  921.     'Cyrillic_zhe_descender' => '0497',
  922.     'Cyrillic_KA_descender' => '049a', # Is this recognised by X ?
  923.     'Cyrillic_ka_descender' => '049b', # Is this recognised by X ?
  924.     'Cyrillic_KA_vertstroke' => '049c', # Is this recognised by X ?
  925.     'Cyrillic_ka_vertstroke' => '049d', # Is this recognised by X ?
  926.     'Cyrillic_EN_descender' => '04a2', # Is this recognised by X ?
  927.     'Cyrillic_en_descender' => '04a3', # Is this recognised by X ?
  928.     'Cyrillic_U_straight' => '04ae', # Is this recognised by X ?
  929.     'Cyrillic_u_straight' => '04af', # Is this recognised by X ?
  930.     'Cyrillic_U_straight_bar' => '04b0', # Is this recognised by X ?
  931.     'Cyrillic_u_straight_bar' => '04b1', # Is this recognised by X ?
  932.     'Cyrillic_HA_descender' => '04b2', # Is this recognised by X ?
  933.     'Cyrillic_ha_descender' => '04b3', # Is this recognised by X ?
  934.     'Cyrillic_CHE_descender' => '04b6',
  935.     'Cyrillic_che_descender' => '04b7',
  936.     'Cyrillic_CHE_vertstroke' => '04b8', # Is this recognised by X ?
  937.     'Cyrillic_che_vertstroke' => '04b9', # Is this recognised by X ?
  938.     'Cyrillic_SHHA' => '04ba', # Is this recognised by X ?
  939.     'Cyrillic_shha' => '04bb', # Is this recognised by X ?
  940.     'Cyrillic_SCHWA' => '04d8', # Is this recognised by X ?
  941.     'Cyrillic_schwa' => '04d9', # Is this recognised by X ?
  942.     'Cyrillic_I_macron' => '04e2',
  943.     'Cyrillic_i_macron' => '04e3',
  944.     'Cyrillic_O_bar' => '04e8', # Is this recognised by X ?
  945.     'Cyrillic_o_bar' => '04e9', # Is this recognised by X ?
  946.     'Cyrillic_U_macron' => '04ee',
  947.     'Cyrillic_u_macron' => '04ef',
  948.     'Armenian_AYB' => '0531',
  949.     'Armenian_BEN' => '0532',
  950.     'Armenian_GIM' => '0533',
  951.     'Armenian_DA' => '0534',
  952.     'Armenian_YECH' => '0535',
  953.     'Armenian_ZA' => '0536',
  954.     'Armenian_E' => '0537',
  955.     'Armenian_AT' => '0538',
  956.     'Armenian_TO' => '0539',
  957.     'Armenian_ZHE' => '053a',
  958.     'Armenian_INI' => '053b',
  959.     'Armenian_LYUN' => '053c',
  960.     'Armenian_KHE' => '053d',
  961.     'Armenian_TSA' => '053e',
  962.     'Armenian_KEN' => '053f',
  963.     'Armenian_HO' => '0540',
  964.     'Armenian_DZA' => '0541',
  965.     'Armenian_GHAT' => '0542',
  966.     'Armenian_TCHE' => '0543',
  967.     'Armenian_MEN' => '0544',
  968.     'Armenian_HI' => '0545',
  969.     'Armenian_NU' => '0546',
  970.     'Armenian_SHA' => '0547',
  971.     'Armenian_VO' => '0548',
  972.     'Armenian_CHA' => '0549',
  973.     'Armenian_PE' => '054a',
  974.     'Armenian_JE' => '054b',
  975.     'Armenian_RA' => '054c',
  976.     'Armenian_SE' => '054d',
  977.     'Armenian_VEV' => '054e',
  978.     'Armenian_TYUN' => '054f',
  979.     'Armenian_RE' => '0550',
  980.     'Armenian_TSO' => '0551',
  981.     'Armenian_VYUN' => '0552',
  982.     'Armenian_PYUR' => '0553',
  983.     'Armenian_KE' => '0554',
  984.     'Armenian_O' => '0555',
  985.     'Armenian_FE' => '0556',
  986.     'Armenian_apostrophe' => '055a',
  987.     'Armenian_accent' => '055b',
  988.     'Armenian_shesht' => '055b',
  989.     'Armenian_amanak' => '055c',
  990.     'Armenian_exclam' => '055c',
  991.     'Armenian_but' => '055d',
  992.     'Armenian_separation_mark' => '055d',
  993.     'Armenian_paruyk' => '055e',
  994.     'Armenian_question' => '055e',
  995.     'Armenian_ayb' => '0561',
  996.     'Armenian_ben' => '0562',
  997.     'Armenian_gim' => '0563',
  998.     'Armenian_da' => '0564',
  999.     'Armenian_yech' => '0565',
  1000.     'Armenian_za' => '0566',
  1001.     'Armenian_e' => '0567',
  1002.     'Armenian_at' => '0568',
  1003.     'Armenian_to' => '0569',
  1004.     'Armenian_zhe' => '056a',
  1005.     'Armenian_ini' => '056b',
  1006.     'Armenian_lyun' => '056c',
  1007.     'Armenian_khe' => '056d',
  1008.     'Armenian_tsa' => '056e',
  1009.     'Armenian_ken' => '056f',
  1010.     'Armenian_ho' => '0570',
  1011.     'Armenian_dza' => '0571',
  1012.     'Armenian_ghat' => '0572',
  1013.     'Armenian_tche' => '0573',
  1014.     'Armenian_men' => '0574',
  1015.     'Armenian_hi' => '0575',
  1016.     'Armenian_nu' => '0576',
  1017.     'Armenian_sha' => '0577',
  1018.     'Armenian_vo' => '0578',
  1019.     'Armenian_cha' => '0579',
  1020.     'Armenian_pe' => '057a',
  1021.     'Armenian_je' => '057b',
  1022.     'Armenian_ra' => '057c',
  1023.     'Armenian_se' => '057d',
  1024.     'Armenian_vev' => '057e',
  1025.     'Armenian_tyun' => '057f',
  1026.     'Armenian_re' => '0580',
  1027.     'Armenian_tso' => '0581',
  1028.     'Armenian_vyun' => '0582',
  1029.     'Armenian_pyur' => '0583',
  1030.     'Armenian_ke' => '0584',
  1031.     'Armenian_o' => '0585',
  1032.     'Armenian_fe' => '0586',
  1033.     'Armenian_ligature_ew' => '0587',
  1034.     'Armenian_full_stop' => '0589',
  1035.     'Armenian_verjaket' => '0589',
  1036.     'Armenian_hyphen' => '058a',
  1037.     'Armenian_yentamna' => '058a',
  1038.     'hebrew_aleph' => '05d0',
  1039.     'hebrew_bet' => '05d1',
  1040.     'hebrew_gimel' => '05d2',
  1041.     'hebrew_dalet' => '05d3',
  1042.     'hebrew_he' => '05d4',
  1043.     'hebrew_waw' => '05d5',
  1044.     'hebrew_zain' => '05d6',
  1045.     'hebrew_chet' => '05d7',
  1046.     'hebrew_tet' => '05d8',
  1047.     'hebrew_yod' => '05d9',
  1048.     'hebrew_finalkaph' => '05da',
  1049.     'hebrew_kaph' => '05db',
  1050.     'hebrew_lamed' => '05dc',
  1051.     'hebrew_finalmem' => '05dd',
  1052.     'hebrew_mem' => '05de',
  1053.     'hebrew_finalnun' => '05df',
  1054.     'hebrew_nun' => '05e0',
  1055.     'hebrew_samech' => '05e1',
  1056.     'hebrew_ayin' => '05e2',
  1057.     'hebrew_finalpe' => '05e3',
  1058.     'hebrew_pe' => '05e4',
  1059.     'hebrew_finalzade' => '05e5',
  1060.     'hebrew_zade' => '05e6',
  1061.     'hebrew_qoph' => '05e7',
  1062.     'hebrew_resh' => '05e8',
  1063.     'hebrew_shin' => '05e9',
  1064.     'hebrew_taw' => '05ea',
  1065.     'Arabic_comma' => '060c',
  1066.     'Arabic_semicolon' => '061b',
  1067.     'Arabic_question_mark' => '061f',
  1068.     'Arabic_hamza' => '0621',
  1069.     'Arabic_maddaonalef' => '0622',
  1070.     'Arabic_hamzaonalef' => '0623',
  1071.     'Arabic_hamzaonwaw' => '0624',
  1072.     'Arabic_hamzaunderalef' => '0625',
  1073.     'Arabic_hamzaonyeh' => '0626',
  1074.     'Arabic_alef' => '0627',
  1075.     'Arabic_beh' => '0628',
  1076.     'Arabic_tehmarbuta' => '0629',
  1077.     'Arabic_teh' => '062a',
  1078.     'Arabic_theh' => '062b',
  1079.     'Arabic_jeem' => '062c',
  1080.     'Arabic_hah' => '062d',
  1081.     'Arabic_khah' => '062e',
  1082.     'Arabic_dal' => '062f',
  1083.     'Arabic_thal' => '0630',
  1084.     'Arabic_ra' => '0631',
  1085.     'Arabic_zain' => '0632',
  1086.     'Arabic_seen' => '0633',
  1087.     'Arabic_sheen' => '0634',
  1088.     'Arabic_sad' => '0635',
  1089.     'Arabic_dad' => '0636',
  1090.     'Arabic_tah' => '0637',
  1091.     'Arabic_zah' => '0638',
  1092.     'Arabic_ain' => '0639',
  1093.     'Arabic_ghain' => '063a',
  1094.     'Arabic_tatweel' => '0640',
  1095.     'Arabic_feh' => '0641',
  1096.     'Arabic_qaf' => '0642',
  1097.     'Arabic_kaf' => '0643',
  1098.     'Arabic_lam' => '0644',
  1099.     'Arabic_meem' => '0645',
  1100.     'Arabic_noon' => '0646',
  1101.     'Arabic_ha' => '0647',
  1102.     'Arabic_heh' => '0647', # Is this recognised by X ?
  1103.     'Arabic_waw' => '0648',
  1104.     'Arabic_alefmaksura' => '0649',
  1105.     'Arabic_yeh' => '064a',
  1106.     'Arabic_fathatan' => '064b',
  1107.     'Arabic_dammatan' => '064c',
  1108.     'Arabic_kasratan' => '064d',
  1109.     'Arabic_fatha' => '064e',
  1110.     'Arabic_damma' => '064f',
  1111.     'Arabic_kasra' => '0650',
  1112.     'Arabic_shadda' => '0651',
  1113.     'Arabic_sukun' => '0652',
  1114.     'Arabic_madda_above' => '0653', # Is this recognised by X ?
  1115.     'Arabic_hamza_above' => '0654', # Is this recognised by X ?
  1116.     'Arabic_hamza_below' => '0655', # Is this recognised by X ?
  1117.     'Arabic_0' => '0660',
  1118.     'Arabic_1' => '0661',
  1119.     'Arabic_2' => '0662',
  1120.     'Arabic_3' => '0663',
  1121.     'Arabic_4' => '0664',
  1122.     'Arabic_5' => '0665',
  1123.     'Arabic_6' => '0666',
  1124.     'Arabic_7' => '0667',
  1125.     'Arabic_8' => '0668',
  1126.     'Arabic_9' => '0669',
  1127.     'Arabic_percent' => '066a',
  1128.     'Arabic_superscript_alef' => '0670', # Is this recognised by X ?
  1129.     'Arabic_tteh' => '0679',
  1130.     'Arabic_peh' => '067e',
  1131.     'Arabic_tcheh' => '0686',
  1132.     'Arabic_ddal' => '0688',
  1133.     'Arabic_rreh' => '0691',
  1134.     'Arabic_jeh' => '0698',
  1135.     'Arabic_veh' => '06a4',
  1136.     'Arabic_keheh' => '06a9',
  1137.     'Arabic_gaf' => '06af',
  1138.     'Arabic_noon_ghunna' => '06ba',
  1139.     'Arabic_heh_doachashmee' => '06be',
  1140.     'Arabic_heh_goal' => '06c1',
  1141.     'Arabic_farsi_yeh' => '06cc',
  1142.     'Farsi_yeh' => '06cc',
  1143.     'Arabic_yeh_baree' => '06d2',
  1144.     'Arabic_fullstop' => '06d4',
  1145.     'Farsi_0' => '06f0',
  1146.     'Farsi_1' => '06f1',
  1147.     'Farsi_2' => '06f2',
  1148.     'Farsi_3' => '06f3',
  1149.     'Farsi_4' => '06f4',
  1150.     'Farsi_5' => '06f5',
  1151.     'Farsi_6' => '06f6',
  1152.     'Farsi_7' => '06f7',
  1153.     'Farsi_8' => '06f8',
  1154.     'Farsi_9' => '06f9',
  1155.     'Thai_kokai' => '0e01',
  1156.     'Thai_khokhai' => '0e02',
  1157.     'Thai_khokhuat' => '0e03',
  1158.     'Thai_khokhwai' => '0e04',
  1159.     'Thai_khokhon' => '0e05',
  1160.     'Thai_khorakhang' => '0e06',
  1161.     'Thai_ngongu' => '0e07',
  1162.     'Thai_chochan' => '0e08',
  1163.     'Thai_choching' => '0e09',
  1164.     'Thai_chochang' => '0e0a',
  1165.     'Thai_soso' => '0e0b',
  1166.     'Thai_chochoe' => '0e0c',
  1167.     'Thai_yoying' => '0e0d',
  1168.     'Thai_dochada' => '0e0e',
  1169.     'Thai_topatak' => '0e0f',
  1170.     'Thai_thothan' => '0e10',
  1171.     'Thai_thonangmontho' => '0e11',
  1172.     'Thai_thophuthao' => '0e12',
  1173.     'Thai_nonen' => '0e13',
  1174.     'Thai_dodek' => '0e14',
  1175.     'Thai_totao' => '0e15',
  1176.     'Thai_thothung' => '0e16',
  1177.     'Thai_thothahan' => '0e17',
  1178.     'Thai_thothong' => '0e18',
  1179.     'Thai_nonu' => '0e19',
  1180.     'Thai_bobaimai' => '0e1a',
  1181.     'Thai_popla' => '0e1b',
  1182.     'Thai_phophung' => '0e1c',
  1183.     'Thai_fofa' => '0e1d',
  1184.     'Thai_phophan' => '0e1e',
  1185.     'Thai_fofan' => '0e1f',
  1186.     'Thai_phosamphao' => '0e20',
  1187.     'Thai_moma' => '0e21',
  1188.     'Thai_yoyak' => '0e22',
  1189.     'Thai_rorua' => '0e23',
  1190.     'Thai_ru' => '0e24',
  1191.     'Thai_loling' => '0e25',
  1192.     'Thai_lu' => '0e26',
  1193.     'Thai_wowaen' => '0e27',
  1194.     'Thai_sosala' => '0e28',
  1195.     'Thai_sorusi' => '0e29',
  1196.     'Thai_sosua' => '0e2a',
  1197.     'Thai_hohip' => '0e2b',
  1198.     'Thai_lochula' => '0e2c',
  1199.     'Thai_oang' => '0e2d',
  1200.     'Thai_honokhuk' => '0e2e',
  1201.     'Thai_paiyannoi' => '0e2f',
  1202.     'Thai_saraa' => '0e30',
  1203.     'Thai_maihanakat' => '0e31',
  1204.     'Thai_saraaa' => '0e32',
  1205.     'Thai_saraam' => '0e33',
  1206.     'Thai_sarai' => '0e34',
  1207.     'Thai_saraii' => '0e35',
  1208.     'Thai_saraue' => '0e36',
  1209.     'Thai_sarauee' => '0e37',
  1210.     'Thai_sarau' => '0e38',
  1211.     'Thai_sarauu' => '0e39',
  1212.     'Thai_phinthu' => '0e3a',
  1213.     'Thai_baht' => '0e3f',
  1214.     'Thai_sarae' => '0e40',
  1215.     'Thai_saraae' => '0e41',
  1216.     'Thai_sarao' => '0e42',
  1217.     'Thai_saraaimaimuan' => '0e43',
  1218.     'Thai_saraaimaimalai' => '0e44',
  1219.     'Thai_lakkhangyao' => '0e45',
  1220.     'Thai_maiyamok' => '0e46',
  1221.     'Thai_maitaikhu' => '0e47',
  1222.     'Thai_maiek' => '0e48',
  1223.     'Thai_maitho' => '0e49',
  1224.     'Thai_maitri' => '0e4a',
  1225.     'Thai_maichattawa' => '0e4b',
  1226.     'Thai_thanthakhat' => '0e4c',
  1227.     'Thai_nikhahit' => '0e4d',
  1228.     'Thai_leksun' => '0e50',
  1229.     'Thai_leknung' => '0e51',
  1230.     'Thai_leksong' => '0e52',
  1231.     'Thai_leksam' => '0e53',
  1232.     'Thai_leksi' => '0e54',
  1233.     'Thai_lekha' => '0e55',
  1234.     'Thai_lekhok' => '0e56',
  1235.     'Thai_lekchet' => '0e57',
  1236.     'Thai_lekpaet' => '0e58',
  1237.     'Thai_lekkao' => '0e59',
  1238.     'Georgian_an' => '10d0',
  1239.     'Georgian_ban' => '10d1',
  1240.     'Georgian_gan' => '10d2',
  1241.     'Georgian_don' => '10d3',
  1242.     'Georgian_en' => '10d4',
  1243.     'Georgian_vin' => '10d5',
  1244.     'Georgian_zen' => '10d6',
  1245.     'Georgian_tan' => '10d7',
  1246.     'Georgian_in' => '10d8',
  1247.     'Georgian_kan' => '10d9',
  1248.     'Georgian_las' => '10da',
  1249.     'Georgian_man' => '10db',
  1250.     'Georgian_nar' => '10dc',
  1251.     'Georgian_on' => '10dd',
  1252.     'Georgian_par' => '10de',
  1253.     'Georgian_zhar' => '10df',
  1254.     'Georgian_rae' => '10e0',
  1255.     'Georgian_san' => '10e1',
  1256.     'Georgian_tar' => '10e2',
  1257.     'Georgian_un' => '10e3',
  1258.     'Georgian_phar' => '10e4',
  1259.     'Georgian_khar' => '10e5',
  1260.     'Georgian_ghan' => '10e6',
  1261.     'Georgian_qar' => '10e7',
  1262.     'Georgian_shin' => '10e8',
  1263.     'Georgian_chin' => '10e9',
  1264.     'Georgian_can' => '10ea',
  1265.     'Georgian_jil' => '10eb',
  1266.     'Georgian_cil' => '10ec',
  1267.     'Georgian_char' => '10ed',
  1268.     'Georgian_xan' => '10ee',
  1269.     'Georgian_jhan' => '10ef',
  1270.     'Georgian_hae' => '10f0',
  1271.     'Georgian_he' => '10f1',
  1272.     'Georgian_hie' => '10f2',
  1273.     'Georgian_we' => '10f3',
  1274.     'Georgian_har' => '10f4',
  1275.     'Georgian_hoe' => '10f5',
  1276.     'Georgian_fi' => '10f6',
  1277.     'Hangul_J_Kiyeog' => '11a8',
  1278.     'Hangul_J_SsangKiyeog' => '11a9',
  1279.     'Hangul_J_KiyeogSios' => '11aa',
  1280.     'Hangul_J_Nieun' => '11ab',
  1281.     'Hangul_J_NieunJieuj' => '11ac',
  1282.     'Hangul_J_NieunHieuh' => '11ad',
  1283.     'Hangul_J_Dikeud' => '11ae',
  1284.     'Hangul_J_Rieul' => '11af',
  1285.     'Hangul_J_RieulKiyeog' => '11b0',
  1286.     'Hangul_J_RieulMieum' => '11b1',
  1287.     'Hangul_J_RieulPieub' => '11b2',
  1288.     'Hangul_J_RieulSios' => '11b3',
  1289.     'Hangul_J_RieulTieut' => '11b4',
  1290.     'Hangul_J_RieulPhieuf' => '11b5',
  1291.     'Hangul_J_RieulHieuh' => '11b6',
  1292.     'Hangul_J_Mieum' => '11b7',
  1293.     'Hangul_J_Pieub' => '11b8',
  1294.     'Hangul_J_PieubSios' => '11b9',
  1295.     'Hangul_J_Sios' => '11ba',
  1296.     'Hangul_J_SsangSios' => '11bb',
  1297.     'Hangul_J_Ieung' => '11bc',
  1298.     'Hangul_J_Jieuj' => '11bd',
  1299.     'Hangul_J_Cieuc' => '11be',
  1300.     'Hangul_J_Khieuq' => '11bf',
  1301.     'Hangul_J_Tieut' => '11c0',
  1302.     'Hangul_J_Phieuf' => '11c1',
  1303.     'Hangul_J_Hieuh' => '11c2',
  1304.     'Hangul_J_PanSios' => '11eb',
  1305.     'Hangul_J_KkogjiDalrinIeung' => '11f0',
  1306.     'Hangul_J_YeorinHieuh' => '11f9',
  1307.     'Babovedot' => '1e02', # Is this recognised by X ?
  1308.     'babovedot' => '1e03', # Is this recognised by X ?
  1309.     'Dabovedot' => '1e0a', # Is this recognised by X ?
  1310.     'dabovedot' => '1e0b', # Is this recognised by X ?
  1311.     'Fabovedot' => '1e1e', # Is this recognised by X ?
  1312.     'fabovedot' => '1e1f', # Is this recognised by X ?
  1313.     'Lbelowdot' => '1e36',
  1314.     'lbelowdot' => '1e37',
  1315.     'Mabovedot' => '1e40', # Is this recognised by X ?
  1316.     'mabovedot' => '1e41', # Is this recognised by X ?
  1317.     'Pabovedot' => '1e56', # Is this recognised by X ?
  1318.     'pabovedot' => '1e57', # Is this recognised by X ?
  1319.     'Sabovedot' => '1e60', # Is this recognised by X ?
  1320.     'sabovedot' => '1e61', # Is this recognised by X ?
  1321.     'Tabovedot' => '1e6a', # Is this recognised by X ?
  1322.     'tabovedot' => '1e6b', # Is this recognised by X ?
  1323.     'Wgrave' => '1e80',
  1324.     'wgrave' => '1e81',
  1325.     'Wacute' => '1e82',
  1326.     'wacute' => '1e83',
  1327.     'Wdiaeresis' => '1e84',
  1328.     'wdiaeresis' => '1e85',
  1329.     'Xabovedot' => '1e8a',
  1330.     'xabovedot' => '1e8b',
  1331.     'Abelowdot' => '1ea0',
  1332.     'abelowdot' => '1ea1',
  1333.     'Ahook' => '1ea2',
  1334.     'ahook' => '1ea3',
  1335.     'Acircumflexacute' => '1ea4',
  1336.     'acircumflexacute' => '1ea5',
  1337.     'Acircumflexgrave' => '1ea6',
  1338.     'acircumflexgrave' => '1ea7',
  1339.     'Acircumflexhook' => '1ea8',
  1340.     'acircumflexhook' => '1ea9',
  1341.     'Acircumflextilde' => '1eaa',
  1342.     'acircumflextilde' => '1eab',
  1343.     'Acircumflexbelowdot' => '1eac',
  1344.     'acircumflexbelowdot' => '1ead',
  1345.     'Abreveacute' => '1eae',
  1346.     'abreveacute' => '1eaf',
  1347.     'Abrevegrave' => '1eb0',
  1348.     'abrevegrave' => '1eb1',
  1349.     'Abrevehook' => '1eb2',
  1350.     'abrevehook' => '1eb3',
  1351.     'Abrevetilde' => '1eb4',
  1352.     'abrevetilde' => '1eb5',
  1353.     'Abrevebelowdot' => '1eb6',
  1354.     'abrevebelowdot' => '1eb7',
  1355.     'Ebelowdot' => '1eb8',
  1356.     'ebelowdot' => '1eb9',
  1357.     'Ehook' => '1eba',
  1358.     'ehook' => '1ebb',
  1359.     'Etilde' => '1ebc',
  1360.     'etilde' => '1ebd',
  1361.     'Ecircumflexacute' => '1ebe',
  1362.     'ecircumflexacute' => '1ebf',
  1363.     'Ecircumflexgrave' => '1ec0',
  1364.     'ecircumflexgrave' => '1ec1',
  1365.     'Ecircumflexhook' => '1ec2',
  1366.     'ecircumflexhook' => '1ec3',
  1367.     'Ecircumflextilde' => '1ec4',
  1368.     'ecircumflextilde' => '1ec5',
  1369.     'Ecircumflexbelowdot' => '1ec6',
  1370.     'ecircumflexbelowdot' => '1ec7',
  1371.     'Ihook' => '1ec8',
  1372.     'ihook' => '1ec9',
  1373.     'Ibelowdot' => '1eca',
  1374.     'ibelowdot' => '1ecb',
  1375.     'Obelowdot' => '1ecc',
  1376.     'obelowdot' => '1ecd',
  1377.     'Ohook' => '1ece',
  1378.     'ohook' => '1ecf',
  1379.     'Ocircumflexacute' => '1ed0',
  1380.     'ocircumflexacute' => '1ed1',
  1381.     'Ocircumflexgrave' => '1ed2',
  1382.     'ocircumflexgrave' => '1ed3',
  1383.     'Ocircumflexhook' => '1ed4',
  1384.     'ocircumflexhook' => '1ed5',
  1385.     'Ocircumflextilde' => '1ed6',
  1386.     'ocircumflextilde' => '1ed7',
  1387.     'Ocircumflexbelowdot' => '1ed8',
  1388.     'ocircumflexbelowdot' => '1ed9',
  1389.     'Ohornacute' => '1eda',
  1390.     'ohornacute' => '1edb',
  1391.     'Ohorngrave' => '1edc',
  1392.     'ohorngrave' => '1edd',
  1393.     'Ohornhook' => '1ede',
  1394.     'ohornhook' => '1edf',
  1395.     'Ohorntilde' => '1ee0',
  1396.     'ohorntilde' => '1ee1',
  1397.     'Ohornbelowdot' => '1ee2',
  1398.     'ohornbelowdot' => '1ee3',
  1399.     'Ubelowdot' => '1ee4',
  1400.     'ubelowdot' => '1ee5',
  1401.     'Uhook' => '1ee6',
  1402.     'uhook' => '1ee7',
  1403.     'Uhornacute' => '1ee8',
  1404.     'uhornacute' => '1ee9',
  1405.     'Uhorngrave' => '1eea',
  1406.     'uhorngrave' => '1eeb',
  1407.     'Uhornhook' => '1eec',
  1408.     'uhornhook' => '1eed',
  1409.     'Uhorntilde' => '1eee',
  1410.     'uhorntilde' => '1eef',
  1411.     'Uhornbelowdot' => '1ef0',
  1412.     'uhornbelowdot' => '1ef1',
  1413.     'Ygrave' => '1ef2',
  1414.     'ygrave' => '1ef3',
  1415.     'Ybelowdot' => '1ef4',
  1416.     'ybelowdot' => '1ef5',
  1417.     'Yhook' => '1ef6',
  1418.     'yhook' => '1ef7',
  1419.     'Ytilde' => '1ef8',
  1420.     'ytilde' => '1ef9',
  1421.     'enspace' => '2002',
  1422.     'emspace' => '2003',
  1423.     'em3space' => '2004',
  1424.     'em4space' => '2005',
  1425.     'digitspace' => '2007',
  1426.     'punctspace' => '2008',
  1427.     'thinspace' => '2009',
  1428.     'hairspace' => '200a',
  1429.     'figdash' => '2012',
  1430.     'endash' => '2013',
  1431.     'emdash' => '2014',
  1432.     'Greek_horizbar' => '2015',
  1433.     'hebrew_doublelowline' => '2017',
  1434.     'leftsinglequotemark' => '2018',
  1435.     'rightsinglequotemark' => '2019',
  1436.     'singlelowquotemark' => '201a',
  1437.     'leftdoublequotemark' => '201c',
  1438.     'rightdoublequotemark' => '201d',
  1439.     'doublelowquotemark' => '201e',
  1440.     'dagger' => '2020',
  1441.     'doubledagger' => '2021',
  1442.     'enfilledcircbullet' => '2022',
  1443.     'doubbaselinedot' => '2025',
  1444.     'ellipsis' => '2026',
  1445.     'minutes' => '2032',
  1446.     'seconds' => '2033',
  1447.     'caret' => '2038',
  1448.     'guilsinglleft' => '2039',
  1449.     'guilsinglright' => '203a',
  1450.     'overline' => '203e',
  1451.     'zerosuperior' => '2070',
  1452.     'foursuperior' => '2074',
  1453.     'fivesuperior' => '2075',
  1454.     'sixsuperior' => '2076',
  1455.     'sevensuperior' => '2077',
  1456.     'eightsuperior' => '2078',
  1457.     'ninesuperior' => '2079',
  1458.     'zerosubscript' => '2080',
  1459.     'onesubscript' => '2081',
  1460.     'twosubscript' => '2082',
  1461.     'threesubscript' => '2083',
  1462.     'foursubscript' => '2084',
  1463.     'fivesubscript' => '2085',
  1464.     'sixsubscript' => '2086',
  1465.     'sevensubscript' => '2087',
  1466.     'eightsubscript' => '2088',
  1467.     'ninesubscript' => '2089',
  1468.     'EcuSign' => '20a0',
  1469.     'ColonSign' => '20a1',
  1470.     'CruzeiroSign' => '20a2',
  1471.     'FFrancSign' => '20a3',
  1472.     'LiraSign' => '20a4',
  1473.     'MillSign' => '20a5',
  1474.     'NairaSign' => '20a6',
  1475.     'PesetaSign' => '20a7',
  1476.     'RupeeSign' => '20a8',
  1477.     'WonSign' => '20a9',
  1478.     'Korean_Won' => '20a9',
  1479.     'NewSheqelSign' => '20aa',
  1480.     'DongSign' => '20ab', # Is this recognised by X ?
  1481.     'EuroSign' => '20ac',
  1482.     'Euro' => '20ac',
  1483.     'careof' => '2105',
  1484.     'numerosign' => '2116',
  1485.     'phonographcopyright' => '2117',
  1486.     'prescription' => '211e',
  1487.     'trademark' => '2122',
  1488.     'onethird' => '2153',
  1489.     'twothirds' => '2154',
  1490.     'onefifth' => '2155',
  1491.     'twofifths' => '2156',
  1492.     'threefifths' => '2157',
  1493.     'fourfifths' => '2158',
  1494.     'onesixth' => '2159',
  1495.     'fivesixths' => '215a',
  1496.     'oneeighth' => '215b',
  1497.     'threeeighths' => '215c',
  1498.     'fiveeighths' => '215d',
  1499.     'seveneighths' => '215e',
  1500.     'leftarrow' => '2190',
  1501.     'uparrow' => '2191',
  1502.     'rightarrow' => '2192',
  1503.     'downarrow' => '2193',
  1504.     'implies' => '21d2',
  1505.     'ifonlyif' => '21d4',
  1506.     'partialderivative' => '2202',
  1507.     'partdifferential' => '2202',
  1508.     'emptyset' => '2205',
  1509.     'nabla' => '2207',
  1510.     'elementof' => '2208',
  1511.     'notelementof' => '2209',
  1512.     'containsas' => '220B',
  1513.     'jot' => '2218',
  1514.     'radical' => '221a',
  1515.     'squareroot' => '221a',
  1516.     'cuberoot' => '221b',
  1517.     'fourthroot' => '221c',
  1518.     'variation' => '221d',
  1519.     'infinity' => '221e',
  1520.     'logicaland' => '2227',
  1521.     'upcaret' => '2227',
  1522.     'downcaret' => '2228',
  1523.     'logicalor' => '2228',
  1524.     'intersection' => '2229',
  1525.     'upshoe' => '2229',
  1526.     'downshoe' => '222a',
  1527.     'union' => '222a',
  1528.     'integral' => '222b',
  1529.     'dintegral' => '222c',
  1530.     'tintegral' => '222d',
  1531.     'therefore' => '2234',
  1532.     'because' => '2235',
  1533.     'approximate' => '223c',
  1534.     'similarequal' => '2243',
  1535.     'notapproxeq' => '2247',
  1536.     'approxeq' => '2248',
  1537.     'notidentical' => '2262',
  1538.     'notequal' => '2260',
  1539.     'identical' => '2261',
  1540.     'stricteq' => '2263',
  1541.     'lessthanequal' => '2264',
  1542.     'greaterthanequal' => '2265',
  1543.     'includedin' => '2282',
  1544.     'leftshoe' => '2282',
  1545.     'includes' => '2283',
  1546.     'rightshoe' => '2283',
  1547.     'lefttack' => '22a2',
  1548.     'righttack' => '22a3',
  1549.     'uptack' => '22a4',
  1550.     'downtack' => '22a5',
  1551.     'upstile' => '2308',
  1552.     'downstile' => '230a',
  1553.     'telephonerecorder' => '2315',
  1554.     'topintegral' => '2320',
  1555.     'botintegral' => '2321',
  1556.     'leftanglebracket' => '2329',
  1557.     'rightanglebracket' => '232a',
  1558.     'quad' => '2395',
  1559.     'topleftparens' => '239b',
  1560.     'botleftparens' => '239d',
  1561.     'toprightparens' => '239e',
  1562.     'botrightparens' => '23a0',
  1563.     'topleftsqbracket' => '23a1',
  1564.     'botleftsqbracket' => '23a3',
  1565.     'toprightsqbracket' => '23a4',
  1566.     'botrightsqbracket' => '23a6',
  1567.     'leftmiddlecurlybrace' => '23a8',
  1568.     'rightmiddlecurlybrace' => '23ac',
  1569.     'leftradical' => '23b7',
  1570.     'horizlinescan1' => '23ba',
  1571.     'horizlinescan3' => '23bb',
  1572.     'horizlinescan7' => '23bc',
  1573.     'horizlinescan9' => '23bd',
  1574.     'ht' => '2409',
  1575.     'lf' => '240a',
  1576.     'vt' => '240b',
  1577.     'ff' => '240c',
  1578.     'cr' => '240d',
  1579.     'nl' => '2424',
  1580.     'horizconnector' => '2500',
  1581.     'horizlinescan5' => '2500',
  1582.     'vertbar' => '2502',
  1583.     'vertconnector' => '2502',
  1584.     'topleftradical' => '250c',
  1585.     'upleftcorner' => '250c',
  1586.     'uprightcorner' => '2510',
  1587.     'lowleftcorner' => '2514',
  1588.     'lowrightcorner' => '2518',
  1589.     'leftt' => '251c',
  1590.     'rightt' => '2524',
  1591.     'topt' => '252c',
  1592.     'bott' => '2534',
  1593.     'crossinglines' => '253c',
  1594.     'checkerboard' => '2592',
  1595.     'enfilledsqbullet' => '25aa',
  1596.     'enopensquarebullet' => '25ab',
  1597.     'filledrectbullet' => '25ac',
  1598.     'openrectbullet' => '25ad',
  1599.     'emfilledrect' => '25ae',
  1600.     'emopenrectangle' => '25af',
  1601.     'filledtribulletup' => '25b2',
  1602.     'opentribulletup' => '25b3',
  1603.     'filledrighttribullet' => '25b6',
  1604.     'rightopentriangle' => '25b7',
  1605.     'filledtribulletdown' => '25bc',
  1606.     'opentribulletdown' => '25bd',
  1607.     'filledlefttribullet' => '25c0',
  1608.     'leftopentriangle' => '25c1',
  1609.     'soliddiamond' => '25c6',
  1610.     'circle' => '25cb',
  1611.     'emopencircle' => '25cb',
  1612.     'emfilledcircle' => '25cf',
  1613.     'enopencircbullet' => '25e6',
  1614.     'openstar' => '2606',
  1615.     'telephone' => '260e',
  1616.     'signaturemark' => '2613',
  1617.     'leftpointer' => '261c',
  1618.     'rightpointer' => '261e',
  1619.     'femalesymbol' => '2640',
  1620.     'malesymbol' => '2642',
  1621.     'club' => '2663',
  1622.     'heart' => '2665',
  1623.     'diamond' => '2666',
  1624.     'musicalflat' => '266d',
  1625.     'musicalsharp' => '266f',
  1626.     'checkmark' => '2713',
  1627.     'ballotcross' => '2717',
  1628.     'latincross' => '271d',
  1629.     'maltesecross' => '2720',
  1630.     'braille_dots_1' => '2801',
  1631.     'braille_dots_2' => '2802',
  1632.     'braille_dots_12' => '2803',
  1633.     'braille_dots_3' => '2804',
  1634.     'braille_dots_13' => '2805',
  1635.     'braille_dots_23' => '2806',
  1636.     'braille_dots_123' => '2807',
  1637.     'braille_dots_4' => '2808',
  1638.     'braille_dots_14' => '2809',
  1639.     'braille_dots_24' => '280a',
  1640.     'braille_dots_124' => '280b',
  1641.     'braille_dots_34' => '280c',
  1642.     'braille_dots_134' => '280d',
  1643.     'braille_dots_234' => '280e',
  1644.     'braille_dots_1234' => '280f',
  1645.     'braille_dots_5' => '2810',
  1646.     'braille_dots_15' => '2811',
  1647.     'braille_dots_25' => '2812',
  1648.     'braille_dots_125' => '2813',
  1649.     'braille_dots_35' => '2814',
  1650.     'braille_dots_135' => '2815',
  1651.     'braille_dots_235' => '2816',
  1652.     'braille_dots_1235' => '2817',
  1653.     'braille_dots_45' => '2818',
  1654.     'braille_dots_145' => '2819',
  1655.     'braille_dots_245' => '281a',
  1656.     'braille_dots_1245' => '281b',
  1657.     'braille_dots_345' => '281c',
  1658.     'braille_dots_1345' => '281d',
  1659.     'braille_dots_2345' => '281e',
  1660.     'braille_dots_12345' => '281f',
  1661.     'braille_dots_6' => '2820',
  1662.     'braille_dots_16' => '2821',
  1663.     'braille_dots_26' => '2822',
  1664.     'braille_dots_126' => '2823',
  1665.     'braille_dots_36' => '2824',
  1666.     'braille_dots_136' => '2825',
  1667.     'braille_dots_236' => '2826',
  1668.     'braille_dots_1236' => '2827',
  1669.     'braille_dots_46' => '2828',
  1670.     'braille_dots_146' => '2829',
  1671.     'braille_dots_246' => '282a',
  1672.     'braille_dots_1246' => '282b',
  1673.     'braille_dots_346' => '282c',
  1674.     'braille_dots_1346' => '282d',
  1675.     'braille_dots_2346' => '282e',
  1676.     'braille_dots_12346' => '282f',
  1677.     'braille_dots_56' => '2830',
  1678.     'braille_dots_156' => '2831',
  1679.     'braille_dots_256' => '2832',
  1680.     'braille_dots_1256' => '2833',
  1681.     'braille_dots_356' => '2834',
  1682.     'braille_dots_1356' => '2835',
  1683.     'braille_dots_2356' => '2836',
  1684.     'braille_dots_12356' => '2837',
  1685.     'braille_dots_456' => '2838',
  1686.     'braille_dots_1456' => '2839',
  1687.     'braille_dots_2456' => '283a',
  1688.     'braille_dots_12456' => '283b',
  1689.     'braille_dots_3456' => '283c',
  1690.     'braille_dots_13456' => '283d',
  1691.     'braille_dots_23456' => '283e',
  1692.     'braille_dots_123456' => '283f',
  1693.     'braille_dots_7' => '2840',
  1694.     'braille_dots_17' => '2841',
  1695.     'braille_dots_27' => '2842',
  1696.     'braille_dots_127' => '2843',
  1697.     'braille_dots_37' => '2844',
  1698.     'braille_dots_137' => '2845',
  1699.     'braille_dots_237' => '2846',
  1700.     'braille_dots_1237' => '2847',
  1701.     'braille_dots_47' => '2848',
  1702.     'braille_dots_147' => '2849',
  1703.     'braille_dots_247' => '284a',
  1704.     'braille_dots_1247' => '284b',
  1705.     'braille_dots_347' => '284c',
  1706.     'braille_dots_1347' => '284d',
  1707.     'braille_dots_2347' => '284e',
  1708.     'braille_dots_12347' => '284f',
  1709.     'braille_dots_57' => '2850',
  1710.     'braille_dots_157' => '2851',
  1711.     'braille_dots_257' => '2852',
  1712.     'braille_dots_1257' => '2853',
  1713.     'braille_dots_357' => '2854',
  1714.     'braille_dots_1357' => '2855',
  1715.     'braille_dots_2357' => '2856',
  1716.     'braille_dots_12357' => '2857',
  1717.     'braille_dots_457' => '2858',
  1718.     'braille_dots_1457' => '2859',
  1719.     'braille_dots_2457' => '285a',
  1720.     'braille_dots_12457' => '285b',
  1721.     'braille_dots_3457' => '285c',
  1722.     'braille_dots_13457' => '285d',
  1723.     'braille_dots_23457' => '285e',
  1724.     'braille_dots_123457' => '285f',
  1725.     'braille_dots_67' => '2860',
  1726.     'braille_dots_167' => '2861',
  1727.     'braille_dots_267' => '2862',
  1728.     'braille_dots_1267' => '2863',
  1729.     'braille_dots_367' => '2864',
  1730.     'braille_dots_1367' => '2865',
  1731.     'braille_dots_2367' => '2866',
  1732.     'braille_dots_12367' => '2867',
  1733.     'braille_dots_467' => '2868',
  1734.     'braille_dots_1467' => '2869',
  1735.     'braille_dots_2467' => '286a',
  1736.     'braille_dots_12467' => '286b',
  1737.     'braille_dots_3467' => '286c',
  1738.     'braille_dots_13467' => '286d',
  1739.     'braille_dots_23467' => '286e',
  1740.     'braille_dots_123467' => '286f',
  1741.     'braille_dots_567' => '2870',
  1742.     'braille_dots_1567' => '2871',
  1743.     'braille_dots_2567' => '2872',
  1744.     'braille_dots_12567' => '2873',
  1745.     'braille_dots_3567' => '2874',
  1746.     'braille_dots_13567' => '2875',
  1747.     'braille_dots_23567' => '2876',
  1748.     'braille_dots_123567' => '2877',
  1749.     'braille_dots_4567' => '2878',
  1750.     'braille_dots_14567' => '2879',
  1751.     'braille_dots_24567' => '287a',
  1752.     'braille_dots_124567' => '287b',
  1753.     'braille_dots_34567' => '287c',
  1754.     'braille_dots_134567' => '287d',
  1755.     'braille_dots_234567' => '287e',
  1756.     'braille_dots_1234567' => '287f',
  1757.     'braille_dots_8' => '2880',
  1758.     'braille_dots_18' => '2881',
  1759.     'braille_dots_28' => '2882',
  1760.     'braille_dots_128' => '2883',
  1761.     'braille_dots_38' => '2884',
  1762.     'braille_dots_138' => '2885',
  1763.     'braille_dots_238' => '2886',
  1764.     'braille_dots_1238' => '2887',
  1765.     'braille_dots_48' => '2888',
  1766.     'braille_dots_148' => '2889',
  1767.     'braille_dots_248' => '288a',
  1768.     'braille_dots_1248' => '288b',
  1769.     'braille_dots_348' => '288c',
  1770.     'braille_dots_1348' => '288d',
  1771.     'braille_dots_2348' => '288e',
  1772.     'braille_dots_12348' => '288f',
  1773.     'braille_dots_58' => '2890',
  1774.     'braille_dots_158' => '2891',
  1775.     'braille_dots_258' => '2892',
  1776.     'braille_dots_1258' => '2893',
  1777.     'braille_dots_358' => '2894',
  1778.     'braille_dots_1358' => '2895',
  1779.     'braille_dots_2358' => '2896',
  1780.     'braille_dots_12358' => '2897',
  1781.     'braille_dots_458' => '2898',
  1782.     'braille_dots_1458' => '2899',
  1783.     'braille_dots_2458' => '289a',
  1784.     'braille_dots_12458' => '289b',
  1785.     'braille_dots_3458' => '289c',
  1786.     'braille_dots_13458' => '289d',
  1787.     'braille_dots_23458' => '289e',
  1788.     'braille_dots_123458' => '289f',
  1789.     'braille_dots_68' => '28a0',
  1790.     'braille_dots_168' => '28a1',
  1791.     'braille_dots_268' => '28a2',
  1792.     'braille_dots_1268' => '28a3',
  1793.     'braille_dots_368' => '28a4',
  1794.     'braille_dots_1368' => '28a5',
  1795.     'braille_dots_2368' => '28a6',
  1796.     'braille_dots_12368' => '28a7',
  1797.     'braille_dots_468' => '28a8',
  1798.     'braille_dots_1468' => '28a9',
  1799.     'braille_dots_2468' => '28aa',
  1800.     'braille_dots_12468' => '28ab',
  1801.     'braille_dots_3468' => '28ac',
  1802.     'braille_dots_13468' => '28ad',
  1803.     'braille_dots_23468' => '28ae',
  1804.     'braille_dots_123468' => '28af',
  1805.     'braille_dots_568' => '28b0',
  1806.     'braille_dots_1568' => '28b1',
  1807.     'braille_dots_2568' => '28b2',
  1808.     'braille_dots_12568' => '28b3',
  1809.     'braille_dots_3568' => '28b4',
  1810.     'braille_dots_13568' => '28b5',
  1811.     'braille_dots_23568' => '28b6',
  1812.     'braille_dots_123568' => '28b7',
  1813.     'braille_dots_4568' => '28b8',
  1814.     'braille_dots_14568' => '28b9',
  1815.     'braille_dots_24568' => '28ba',
  1816.     'braille_dots_124568' => '28bb',
  1817.     'braille_dots_34568' => '28bc',
  1818.     'braille_dots_134568' => '28bd',
  1819.     'braille_dots_234568' => '28be',
  1820.     'braille_dots_1234568' => '28bf',
  1821.     'braille_dots_78' => '28c0',
  1822.     'braille_dots_178' => '28c1',
  1823.     'braille_dots_278' => '28c2',
  1824.     'braille_dots_1278' => '28c3',
  1825.     'braille_dots_378' => '28c4',
  1826.     'braille_dots_1378' => '28c5',
  1827.     'braille_dots_2378' => '28c6',
  1828.     'braille_dots_12378' => '28c7',
  1829.     'braille_dots_478' => '28c8',
  1830.     'braille_dots_1478' => '28c9',
  1831.     'braille_dots_2478' => '28ca',
  1832.     'braille_dots_12478' => '28cb',
  1833.     'braille_dots_3478' => '28cc',
  1834.     'braille_dots_13478' => '28cd',
  1835.     'braille_dots_23478' => '28ce',
  1836.     'braille_dots_123478' => '28cf',
  1837.     'braille_dots_578' => '28d0',
  1838.     'braille_dots_1578' => '28d1',
  1839.     'braille_dots_2578' => '28d2',
  1840.     'braille_dots_12578' => '28d3',
  1841.     'braille_dots_3578' => '28d4',
  1842.     'braille_dots_13578' => '28d5',
  1843.     'braille_dots_23578' => '28d6',
  1844.     'braille_dots_123578' => '28d7',
  1845.     'braille_dots_4578' => '28d8',
  1846.     'braille_dots_14578' => '28d9',
  1847.     'braille_dots_24578' => '28da',
  1848.     'braille_dots_124578' => '28db',
  1849.     'braille_dots_34578' => '28dc',
  1850.     'braille_dots_134578' => '28dd',
  1851.     'braille_dots_234578' => '28de',
  1852.     'braille_dots_1234578' => '28df',
  1853.     'braille_dots_678' => '28e0',
  1854.     'braille_dots_1678' => '28e1',
  1855.     'braille_dots_2678' => '28e2',
  1856.     'braille_dots_12678' => '28e3',
  1857.     'braille_dots_3678' => '28e4',
  1858.     'braille_dots_13678' => '28e5',
  1859.     'braille_dots_23678' => '28e6',
  1860.     'braille_dots_123678' => '28e7',
  1861.     'braille_dots_4678' => '28e8',
  1862.     'braille_dots_14678' => '28e9',
  1863.     'braille_dots_24678' => '28ea',
  1864.     'braille_dots_124678' => '28eb',
  1865.     'braille_dots_34678' => '28ec',
  1866.     'braille_dots_134678' => '28ed',
  1867.     'braille_dots_234678' => '28ee',
  1868.     'braille_dots_1234678' => '28ef',
  1869.     'braille_dots_5678' => '28f0',
  1870.     'braille_dots_15678' => '28f1',
  1871.     'braille_dots_25678' => '28f2',
  1872.     'braille_dots_125678' => '28f3',
  1873.     'braille_dots_35678' => '28f4',
  1874.     'braille_dots_135678' => '28f5',
  1875.     'braille_dots_235678' => '28f6',
  1876.     'braille_dots_1235678' => '28f7',
  1877.     'braille_dots_45678' => '28f8',
  1878.     'braille_dots_145678' => '28f9',
  1879.     'braille_dots_245678' => '28fa',
  1880.     'braille_dots_1245678' => '28fb',
  1881.     'braille_dots_345678' => '28fc',
  1882.     'braille_dots_1345678' => '28fd',
  1883.     'braille_dots_2345678' => '28fe',
  1884.     'braille_dots_12345678' => '28ff',
  1885.     'kana_comma' => '3001',
  1886.     'kana_fullstop' => '3002',
  1887.     'kana_openingbracket' => '300c',
  1888.     'kana_closingbracket' => '300d',
  1889.     'voicedsound' => '309b',
  1890.     'semivoicedsound' => '309c',
  1891.     'kana_a' => '30a1',
  1892.     'kana_A' => '30a2',
  1893.     'kana_i' => '30a3',
  1894.     'kana_I' => '30a4',
  1895.     'kana_u' => '30a5',
  1896.     'kana_U' => '30a6',
  1897.     'kana_e' => '30a7',
  1898.     'kana_E' => '30a8',
  1899.     'kana_o' => '30a9',
  1900.     'kana_O' => '30aa',
  1901.     'kana_KA' => '30ab',
  1902.     'kana_KI' => '30ad',
  1903.     'kana_KU' => '30af',
  1904.     'kana_KE' => '30b1',
  1905.     'kana_KO' => '30b3',
  1906.     'kana_SA' => '30b5',
  1907.     'kana_SHI' => '30b7',
  1908.     'kana_SU' => '30b9',
  1909.     'kana_SE' => '30bb',
  1910.     'kana_SO' => '30bd',
  1911.     'kana_TA' => '30bf',
  1912.     'kana_CHI' => '30c1',
  1913.     'kana_tsu' => '30c3',
  1914.     'kana_TSU' => '30c4',
  1915.     'kana_TE' => '30c6',
  1916.     'kana_TO' => '30c8',
  1917.     'kana_NA' => '30ca',
  1918.     'kana_NI' => '30cb',
  1919.     'kana_NU' => '30cc',
  1920.     'kana_NE' => '30cd',
  1921.     'kana_NO' => '30ce',
  1922.     'kana_HA' => '30cf',
  1923.     'kana_HI' => '30d2',
  1924.     'kana_FU' => '30d5',
  1925.     'kana_HE' => '30d8',
  1926.     'kana_HO' => '30db',
  1927.     'kana_MA' => '30de',
  1928.     'kana_MI' => '30df',
  1929.     'kana_MU' => '30e0',
  1930.     'kana_ME' => '30e1',
  1931.     'kana_MO' => '30e2',
  1932.     'kana_ya' => '30e3',
  1933.     'kana_YA' => '30e4',
  1934.     'kana_yu' => '30e5',
  1935.     'kana_YU' => '30e6',
  1936.     'kana_yo' => '30e7',
  1937.     'kana_YO' => '30e8',
  1938.     'kana_RA' => '30e9',
  1939.     'kana_RI' => '30ea',
  1940.     'kana_RU' => '30eb',
  1941.     'kana_RE' => '30ec',
  1942.     'kana_RO' => '30ed',
  1943.     'kana_WA' => '30ef',
  1944.     'kana_WO' => '30f2',
  1945.     'kana_N' => '30f3',
  1946.     'kana_conjunctive' => '30fb',
  1947.     'kana_middledot' => '30fb', # Is this recognised by X ?
  1948.     'prolongedsound' => '30fc',
  1949.     'Hangul_Kiyeog' => '3131',
  1950.     'Hangul_SsangKiyeog' => '3132',
  1951.     'Hangul_KiyeogSios' => '3133',
  1952.     'Hangul_Nieun' => '3134',
  1953.     'Hangul_NieunJieuj' => '3135',
  1954.     'Hangul_NieunHieuh' => '3136',
  1955.     'Hangul_Dikeud' => '3137',
  1956.     'Hangul_SsangDikeud' => '3138',
  1957.     'Hangul_Rieul' => '3139',
  1958.     'Hangul_RieulKiyeog' => '313a',
  1959.     'Hangul_RieulMieum' => '313b',
  1960.     'Hangul_RieulPieub' => '313c',
  1961.     'Hangul_RieulSios' => '313d',
  1962.     'Hangul_RieulTieut' => '313e',
  1963.     'Hangul_RieulPhieuf' => '313f',
  1964.     'Hangul_RieulHieuh' => '3140',
  1965.     'Hangul_Mieum' => '3141',
  1966.     'Hangul_Pieub' => '3142',
  1967.     'Hangul_SsangPieub' => '3143',
  1968.     'Hangul_PieubSios' => '3144',
  1969.     'Hangul_Sios' => '3145',
  1970.     'Hangul_SsangSios' => '3146',
  1971.     'Hangul_Ieung' => '3147',
  1972.     'Hangul_Jieuj' => '3148',
  1973.     'Hangul_SsangJieuj' => '3149',
  1974.     'Hangul_Cieuc' => '314a',
  1975.     'Hangul_Khieuq' => '314b',
  1976.     'Hangul_Tieut' => '314c',
  1977.     'Hangul_Phieuf' => '314d',
  1978.     'Hangul_Hieuh' => '314e',
  1979.     'Hangul_A' => '314f',
  1980.     'Hangul_AE' => '3150',
  1981.     'Hangul_YA' => '3151',
  1982.     'Hangul_YAE' => '3152',
  1983.     'Hangul_EO' => '3153',
  1984.     'Hangul_E' => '3154',
  1985.     'Hangul_YEO' => '3155',
  1986.     'Hangul_YE' => '3156',
  1987.     'Hangul_O' => '3157',
  1988.     'Hangul_WA' => '3158',
  1989.     'Hangul_WAE' => '3159',
  1990.     'Hangul_OE' => '315a',
  1991.     'Hangul_YO' => '315b',
  1992.     'Hangul_U' => '315c',
  1993.     'Hangul_WEO' => '315d',
  1994.     'Hangul_WE' => '315e',
  1995.     'Hangul_WI' => '315f',
  1996.     'Hangul_YU' => '3160',
  1997.     'Hangul_EU' => '3161',
  1998.     'Hangul_YI' => '3162',
  1999.     'Hangul_I' => '3163',
  2000.     'Hangul_RieulYeorinHieuh' => '316d',
  2001.     'Hangul_SunkyeongeumMieum' => '3171',
  2002.     'Hangul_SunkyeongeumPieub' => '3178',
  2003.     'Hangul_PanSios' => '317f',
  2004.     'Hangul_KkogjiDalrinIeung' => '3181',
  2005.     'Hangul_SunkyeongeumPhieuf' => '3184',
  2006.     'Hangul_YeorinHieuh' => '3186',
  2007.     'Hangul_AraeA' => '318d',
  2008.     'Hangul_AraeAE' => '318e',
  2009. );
  2010.  
  2011. if ($freebsd) {
  2012.     %xkbsym_table = 
  2013.         (%xkbsym_table,
  2014. # Control symbols
  2015.          'BackSpace' => 'bs',      # 0008
  2016.          'Tab' => 'ht',            # 0009
  2017.          'Linefeed' => 'nl',       # 000a
  2018.          'Return' => 'cr',         # 000d
  2019.          'Escape' => 'esc',        # 001b
  2020. # Keypad keys
  2021.          'KP_Multiply' => '\'*\'',
  2022.          'KP_Add' => 'fkey56',
  2023.          'KP_Seprator' => '\',\'', # Is this recognised by X ?
  2024.          'KP_Separator' => '\',\'',
  2025.          'KP_Subtract' => 'fkey52',
  2026.          'KP_Decimal' => '\'.\'',
  2027.          'KP_Divide' => '\'/\'',
  2028.          'KP_0' => '\'0\'',
  2029.          'KP_1' => '\'1\'',
  2030.          'KP_2' => '\'2\'',
  2031.          'KP_3' => '\'3\'',
  2032.          'KP_4' => '\'4\'',
  2033.          'KP_5' => '\'5\'',
  2034.          'KP_6' => '\'6\'',
  2035.          'KP_7' => '\'7\'',
  2036.          'KP_8' => '\'8\'',
  2037.          'KP_9' => '\'9\'',
  2038.          'KP_Enter' => 'cr',
  2039.          'KP_Home' => 'fkey49',
  2040.          'KP_Left' => 'fkey53',
  2041.          'KP_Up' => 'fkey50',
  2042.          'KP_Right' => 'fkey55',
  2043.          'KP_Down' => 'fkey58',
  2044.          'KP_Prior' => 'fkey51',
  2045.          'KP_Page_Up' => 'fkey51',
  2046.          'KP_Next' => 'fkey59',
  2047.          'KP_Page_Down' => 'fkey59',
  2048.          'KP_End' => 'fkey57',
  2049.          'KP_Begin' => 'fkey54',
  2050.          'KP_Insert' => 'fkey60',
  2051.          'KP_Delete' => 'del',
  2052.          'KP_Space' => 'sp',
  2053.          'KP_Equal' => '\'=\'',
  2054.          'KP_Tab' => 'ht',
  2055.          'KP_F1' => 'fkey01',
  2056.          'KP_F2' => 'fkey02',
  2057.          'KP_F3' => 'fkey03',
  2058.          'KP_F4' => 'fkey04',
  2059. # Dead symbols
  2060.          'dead_grave' => 'dgra',
  2061.          'SunFA_Grave' => 'dgra_grave', # Is this recognised by X ?
  2062.          'dead_acute' => 'dacu',
  2063.          'SunFA_Acute' => 'dacu', # Is this recognised by X ?
  2064.          'dead_circumflex' => 'dcir',
  2065.          'SunFA_Circum' => 'dcir', # Is this recognised by X ?
  2066.          'dead_tilde' => 'dtil',
  2067.          'SunFA_Tilde' => 'dtil',
  2068.          'dead_breve' => 'dbre',
  2069.          'dead_diaeresis' => 'ddia',
  2070.          'SunFA_Diaeresis' => 'ddia', # Is this recognised by X ?
  2071.          'dead_doubleacute' => 'ddac',
  2072.          'dead_caron' => 'dcar',
  2073.          'dead_V' => 'dcar', # Is this correct?
  2074.          'dead_cedilla' => 'dced',
  2075.          'SunFA_Cedilla' => 'dced', # Is this recognised by X ?
  2076.          'dead_ogonek' => 'dogo',
  2077.          'dead_macron' => 'dmac',
  2078.          'dead_abovedot' => 'ddot',
  2079.          'dead_abovering' => 'drin',
  2080.          'dead_stroke' => 'nop',
  2081.          'dead_belowdot' => '0323',       # ???? Vietnamese
  2082.          'dead_hook' => 'dsla',           # ???? Vietnamese
  2083.          'dead_belowcomma' => 'nop',
  2084.          'dead_currency' => 'nop',
  2085.          'dead_doublegrave' => 'nop',
  2086.          'dead_invertedbreve' => 'nop',
  2087.          'dead_iota' => '03b9',           # ???? Greek
  2088.          'dead_horn' => '031b',           # ???? Greek
  2089.          'dead_psili' => 'nop',           # ???? Greek
  2090.          'dead_dasia' => 'nop',           # ???? Greek
  2091. # Modifiers
  2092.          'Multi_key' => 'nop',
  2093.          'Mode_switch' => 'ashift',
  2094.          'script_switch' => 'nop',
  2095.          'Shift_L' => 'lshift',
  2096.          'Shift_R' => 'rshift',
  2097.          'Control_L' => 'lctrl',
  2098.          'Control_R' => 'rctrl',
  2099.          'Caps_Lock' => 'clock',
  2100.          'Shift_Lock' => 'clock',
  2101.          'Meta_L' => 'meta',
  2102.          'Meta_R' => 'meta',
  2103.          'Alt_L' => 'lalt',
  2104.          'Alt_R' => 'ralt',
  2105.          'Super_L' => 'fkey62',
  2106.          'Super_R' => 'fkey63',
  2107.          'Hyper_L' => 'meta',
  2108.          'Hyper_R' => 'meta',
  2109.          'ISO_Lock' => 'clock',
  2110.          'ISO_Level2_Latch' => 'lshift',
  2111.          'ISO_Level3_Shift' => 'alt',
  2112.          'ISO_Level3_Latch' => 'alt',
  2113.          'ISO_Level3_Lock' => 'alta',
  2114.          'ISO_Level5_Shift' => 'alt',
  2115.          'ISO_Level5_Latch' => 'alt',
  2116.          'ISO_Level5_Lock' => 'alta',
  2117.          'ISO_Group_Shift' => 'ashift',
  2118.          'ISO_Group_Latch' => 'ashift',
  2119.          'ISO_Group_Lock' => 'alock',
  2120.          'ISO_Next_Group' => 'alock',
  2121.          'ISO_Next_Group_Lock' => 'alock',
  2122.          'ISO_Prev_Group' => 'alock',
  2123.          'ISO_Prev_Group_Lock' => 'alock',
  2124.          'ISO_First_Group' => 'alock',
  2125.          'ISO_First_Group_Lock' => 'alock',
  2126.          'ISO_Last_Group' => 'alock',
  2127.          'ISO_Last_Group_Lock' => 'alock',
  2128. # Other symbols
  2129.          'NoAction' => 'NoSymbol', # Is this recognised by X ?
  2130.          'nosymbol' => 'NoSymbol', # Is this recognised by X ?
  2131.          'Nosymbol' => 'NoSymbol', # Is this recognised by X ?
  2132.          'noSymbol' => 'NoSymbol', # Is this recognised by X ?
  2133.          'NoSymbol' => 'NoSymbol',
  2134.          'any' => 'NoSymbol', # Is this recognised by X ?
  2135.          'VoidSymbol' => 'nop',
  2136.          'voidsymbol' => 'nop', # Is this recognised by X ?
  2137.          'ISO_Left_Tab' => 'ht',
  2138.          'Clear' => 'nop',
  2139.          'Pause' => 'saver',
  2140.          'Scroll_Lock' => 'slock',
  2141.          'Sys_Req' => 'nop',
  2142.          'Delete' => 'fkey61',
  2143.          'Codeinput' => 'nop',
  2144.          'SingleCandidate' => 'nop',
  2145.          'MultipleCandidate' => 'nop',
  2146.          'PreviousCandidate' => 'nop',
  2147.          'Home' => 'fkey49',
  2148.          'Left' => 'fkey53',
  2149.          'Up' => 'fkey50',
  2150.          'Right' => 'fkey55',
  2151.          'Down' => 'fkey58',
  2152.          'Prior' => 'fkey51',
  2153.          'Page_Up' => 'fkey51',
  2154.          'Next' => 'fkey59',
  2155.          'Page_Down' => 'fkey59',
  2156.          'End' => 'fkey57',
  2157.          'Begin' => 'fkey54',
  2158.          'Select' => 'fkey57',
  2159.          'Print' => 'nscr',
  2160.          'Execute' => 'nop',
  2161.          'Insert' => 'fkey60',
  2162.          'Undo' => 'nop',
  2163.          'Redo' => 'nop',
  2164.          'Menu' => 'fkey64',
  2165.          'Find' => 'fkey49',
  2166.          'Cancel' => 'nop',
  2167.          'Help' => 'slock', # Is this correct?
  2168.          'Break' => 'nop',
  2169.          'Num_Lock' => 'nlock',
  2170.          'F1' => 'fkey01',
  2171.          'F2' => 'fkey02',
  2172.          'F3' => 'fkey03',
  2173.          'F4' => 'fkey04',
  2174.          'F5' => 'fkey05',
  2175.          'F6' => 'fkey06',
  2176.          'F7' => 'fkey07',
  2177.          'F8' => 'fkey08',
  2178.          'F9' => 'fkey09',
  2179.          'F10' => 'fkey10',
  2180.          'F11' => 'fkey11',
  2181.          'L1' => 'fkey11',
  2182.          'F12' => 'fkey12',
  2183.          'L2' => 'fkey12',
  2184.          'F13' => 'fkey13',
  2185.          'L3' => 'fkey13',
  2186.          'F14' => 'fkey14',
  2187.          'L4' => 'fkey14',
  2188.          'F15' => 'fkey15',
  2189.          'L5' => 'fkey15',
  2190.          'F16' => 'fkey16',
  2191.          'L6' => 'fkey16',
  2192.          'F17' => 'fkey17',
  2193.          'L7' => 'fkey17',
  2194.          'F18' => 'fkey18',
  2195.          'L8' => 'fkey18',
  2196.          'F19' => 'fkey19',
  2197.          'L9' => 'fkey19',
  2198.          'F20' => 'fkey20',
  2199.          'L10' => 'fkey20',
  2200.          'F21' => 'fkey21',
  2201.          'R1' => 'fkey21',
  2202.          'F22' => 'fkey22',
  2203.          'R2' => 'fkey22',
  2204.          'F23' => 'fkey23',
  2205.          'R3' => 'fkey23',
  2206.          'F24' => 'fkey24',
  2207.          'R4' => 'fkey24',
  2208.          'F25' => 'fkey25',
  2209.          'R5' => 'fkey25',
  2210.          'F26' => 'fkey26',
  2211.          'R6' => 'fkey26',
  2212.          'F27' => 'fkey27',
  2213.          'R7' => 'fkey27',
  2214.          'F28' => 'fkey28',
  2215.          'R8' => 'fkey28',
  2216.          'F29' => 'fkey29',
  2217.          'R9' => 'fkey29',
  2218.          'F30' => 'fkey30',
  2219.          'R10' => 'fkey30',
  2220.          'F31' => 'fkey31',
  2221.          'R11' => 'fkey31',
  2222.          'F32' => 'fkey32',
  2223.          'R12' => 'fkey32',
  2224.          'F33' => 'fkey33',
  2225.          'R13' => 'fkey33',
  2226.          'F34' => 'fkey34',
  2227.          'R14' => 'fkey34',
  2228.          'F35' => 'fkey35',
  2229.          'R15' => 'fkey35',
  2230.          'Terminate_Server' => 'nop',
  2231.          'Pointer_EnableKeys' => 'nop',
  2232.          'XF86_Switch_VT_1' => 'scr01',
  2233.          'XF86_Switch_VT_2' => 'scr02',
  2234.          'XF86_Switch_VT_3' => 'scr03',
  2235.          'XF86_Switch_VT_4' => 'scr04',
  2236.          'XF86_Switch_VT_5' => 'scr05',
  2237.          'XF86_Switch_VT_6' => 'scr06',
  2238.          'XF86_Switch_VT_7' => 'scr07',
  2239.          'XF86_Switch_VT_8' => 'scr08',
  2240.          'XF86_Switch_VT_9' => 'scr09',
  2241.          'XF86_Switch_VT_10' => 'scr10',
  2242.          'XF86_Switch_VT_11' => 'scr11',
  2243.          'XF86_Switch_VT_12' => 'scr12',
  2244.          'XF86_ClearGrab' => 'nop',
  2245.          'XF86_Ungrab' => 'nop',
  2246.          'XF86_Next_VMode' => 'nop',
  2247.          'XF86_Prev_VMode' => 'nop',
  2248.          'XF86Copy' => 'nop',
  2249.          'XF86Cut' => 'nop',
  2250.          'XF86Paste' => 'nop',
  2251.          'XF86AudioLowerVolume' => 'nop',
  2252.          'XF86AudioRaiseVolume' => 'nop',
  2253.          'XF86AudioMute' => 'nop',
  2254.          'XF86PowerOff' => 'nop',
  2255.          'XF86AudioForward' => 'nop',
  2256.          'XF86AudioMedia' => 'nop',
  2257.          'XF86AudioNext' => 'nop',
  2258.          'XF86AudioPause' => 'nop',
  2259.          'XF86AudioPlay' => 'nop',
  2260.          'XF86AudioPrev' => 'nop',
  2261.          'XF86AudioRecord' => 'nop',
  2262.          'XF86AudioRewind' => 'nop',
  2263.          'XF86AudioStop' => 'nop',
  2264.          'XF86Back' => 'nop',
  2265.          'XF86Battery' => 'nop',
  2266.          'XF86Bluetooth' => 'nop',
  2267.          'XF86Calculator' => 'nop',
  2268.          'XF86Close' => 'nop',
  2269.          'XF86Display' => 'nop',
  2270.          'XF86Documents' => 'nop',
  2271.          'XF86DOS' => 'nop',
  2272.          'XF86Eject' => 'nop',
  2273.          'XF86Explorer' => 'nop',
  2274.          'XF86Favorites' => 'nop',
  2275.          'XF86Finance' => 'nop',
  2276.          'XF86Forward' => 'nop',
  2277.          'XF86HomePage' => 'nop',
  2278.          'XF86KbdBrightnessDown' => 'nop',
  2279.          'XF86KbdBrightnessUp' => 'nop',
  2280.          'XF86KbdLightOnOff' => 'nop',
  2281.          'XF86Launch1' => 'nop',
  2282.          'XF86Launch2' => 'nop',
  2283.          'XF86Launch3' => 'nop',
  2284.          'XF86Launch4' => 'nop',
  2285.          'XF86Mail' => 'nop',
  2286.          'XF86MailForward' => 'nop',
  2287.          'XF86MenuKB' => 'nop',
  2288.          'XF86MonBrightnessDown' => 'nop',
  2289.          'XF86MonBrightnessUp' => 'nop',
  2290.          'XF86MyComputer' => 'nop',
  2291.          'XF86New' => 'nop',
  2292.          'XF86Phone' => 'nop',
  2293.          'XF86Reload' => 'nop',
  2294.          'XF86Reply' => 'nop',
  2295.          'XF86RotateWindows' => 'nop',
  2296.          'XF86Save' => 'nop',
  2297.          'XF86ScreenSaver' => 'nop',
  2298.          'XF86ScrollDown' => 'nop',
  2299.          'XF86ScrollUp' => 'nop',
  2300.          'XF86Search' => 'nop',
  2301.          'XF86Send' => 'nop',
  2302.          'XF86Shop' => 'nop',
  2303.          'XF86Sleep' => 'nop',
  2304.          'XF86Suspend' => 'nop',
  2305.          'XF86Tools' => 'nop',
  2306.          'XF86TouchpadToggle' => 'nop',
  2307.          'XF86WakeUp' => 'nop',
  2308.          'XF86WebCam' => 'nop',
  2309.          'XF86WLAN' => 'nop',
  2310.          'XF86WWW' => 'nop',
  2311.          'XF86Xfer' => 'nop',
  2312.          'braille_blank' => '2800', # What does correspond to these?
  2313.          'braille_dot_1' => 'nop', 
  2314.          'braille_dot_2' => 'nop',
  2315.          'braille_dot_3' => 'nop',
  2316.          'braille_dot_4' => 'nop',
  2317.          'braille_dot_5' => 'nop',
  2318.          'braille_dot_6' => 'nop',
  2319.          'braille_dot_7' => 'nop',
  2320.          'braille_dot_8' => 'nop',
  2321.          'braille_dot_9' => 'nop',
  2322.          'braille_dot_10' => 'nop',
  2323. # I do not know the Unicodes of these
  2324.          '0x1000' => 'nop', # Special symbol for X or syntax error?
  2325.          '0x13a4' => 'nop', # Special symbol for X or syntax error?
  2326.          '0xfe11' => 'nop', # Special symbol for X or syntax error?
  2327.          'leftcaret' => 'nop', # Is this recognised by X ?
  2328.          'guj_rra' => 'nop', # Is this recognised by X ?
  2329.          'guj_nnna' => 'nop', # Is this recognised by X ?
  2330.          'guj_llla' => 'nop', # Is this recognised by X ?
  2331.          'gur_visarga' => 'nop', # Is this recognised by X ?
  2332.          'gur_v_r' => 'nop', # Is this recognised by X ?
  2333.          'gur_v_r_s' => 'nop', # Is this recognised by X ?
  2334.          'Eisu_toggle' => 'nop', # Is this recognised by X ?
  2335.          'Zenkaku_Hankaku' => 'nop', # Is this recognised by X ?
  2336.          'Kanji' => 'nop', # Is this recognised by X ?
  2337.          'Hangul' => 'nop', # Is this recognised by X ?
  2338.          'Hangul_Hanja' => 'nop', # Is this recognised by X ?
  2339.          'Henkan' => 'nop',
  2340.          'Hiragana' => 'nop',
  2341.          'Hiragana_Katakana' => 'nop',
  2342.          'Katakana' => 'nop',
  2343.          'Muhenkan' => 'nop',
  2344. # XFree86 does not recognise these
  2345.          'SunAudioLowerVolume' => 'nop',
  2346.          'SunAudioRaiseVolume' => 'nop',
  2347.          'SunAudioMute' => 'nop',
  2348.          'SunCopy' => 'nop',
  2349.          'SunCut' => 'nop',
  2350.          'SunPaste' => 'nop',
  2351.          'SunAgain' => 'nop',
  2352.          'SunUndo' => 'nop',
  2353.          'SunFind' => 'nop',
  2354.          'SunStop' => 'nop',
  2355.          'SunF36' => 'nop',
  2356.          'SunF37' => 'nop',
  2357.          'SunFront' => 'nop',
  2358.          'SunOpen' => 'nop',
  2359.          'SunPowerSwitch' => 'nop',
  2360.          'SunPowerSwitchShift' => 'nop',
  2361.          'SunProps' => 'nop',
  2362.          'SunSys_Req' => 'nop',
  2363.          'SunVideoDegauss' => 'nop',
  2364.          'SunVideoLowerBrightness' => 'nop',
  2365.          'SunVideoRaiseBrightness' => 'nop',
  2366.         );
  2367.     if ($backspace eq 'del') {
  2368.         $xkbsym_table{'BackSpace'} = 'del';
  2369.         $xkbsym_table{'Delete'} = 'fkey70';
  2370.         $xkbsym_table{'KP_Delete'} = 'fkey70';
  2371.     }
  2372. } else {
  2373.     %xkbsym_table = 
  2374.         (%xkbsym_table,
  2375. # Control symbols
  2376.          'BackSpace' => 'Delete',  # 0008
  2377.          'Tab' => 'Tab',           # 0009
  2378.          'Linefeed' => 'Linefeed', # 000a
  2379.          'Return' => 'Return',     # 000d
  2380.          'Escape' => 'Escape',     # 001b
  2381. # Keypad keys
  2382.          'KP_Multiply' => 'KP_Multiply',
  2383.          'KP_Add' => 'KP_Add',
  2384.          'KP_Seprator' => 'KP_Comma', # Is this recognised by X ?
  2385.          'KP_Separator' => 'KP_Comma',
  2386.          'KP_Subtract' => 'KP_Subtract',
  2387.          'KP_Decimal' => 'KP_Period',
  2388.          'KP_Divide' => 'KP_Divide',
  2389.          'KP_0' => 'KP_0',
  2390.          'KP_1' => 'KP_1',
  2391.          'KP_2' => 'KP_2',
  2392.          'KP_3' => 'KP_3',
  2393.          'KP_4' => 'KP_4',
  2394.          'KP_5' => 'KP_5',
  2395.          'KP_6' => 'KP_6',
  2396.          'KP_7' => 'KP_7',
  2397.          'KP_8' => 'KP_8',
  2398.          'KP_9' => 'KP_9',
  2399.          'KP_Enter' => 'KP_Enter',
  2400. # Keypad keys (alternate level)
  2401.          'KP_Home' => 'KP_7',
  2402.          'KP_Left' => 'KP_4',
  2403.          'KP_Up' => 'KP_8',
  2404.          'KP_Right' => 'KP_6',
  2405.          'KP_Down' => 'KP_2',
  2406.          'KP_Prior' => 'KP_9',
  2407.          'KP_Page_Up' => 'KP_9',
  2408.          'KP_Next' => 'KP_3',
  2409.          'KP_Page_Down' => 'KP_3',
  2410.          'KP_End' => 'KP_1',
  2411.          'KP_Begin' => 'VoidSymbol', # What does correspond to this?
  2412.          'KP_Insert' => 'KP_0',
  2413.          'KP_Delete' => 'VoidSymbol', # has to be 'KP_Period' or 'KP_Decimal'
  2414. # Keypad keys with missing support in the kernel
  2415.          'KP_Space' => 'space',
  2416.          'KP_Equal' => 'equal',
  2417.          'KP_Tab' => 'Tab',
  2418.          'KP_F1' => 'F1',
  2419.          'KP_F2' => 'F2',
  2420.          'KP_F3' => 'F3',
  2421.          'KP_F4' => 'F4',
  2422. # Dead symbols
  2423.          'dead_grave' => 'dead_grave',
  2424.          'SunFA_Grave' => 'dead_grave', # Is this recognised by X ?
  2425.          'dead_acute' => 'dead_acute',
  2426.          'SunFA_Acute' => 'dead_acute', # Is this recognised by X ?
  2427.          'dead_circumflex' => 'dead_circumflex',
  2428.          'SunFA_Circum' => 'dead_circumflex', # Is this recognised by X ?
  2429.          'dead_tilde' => 'dead_tilde',
  2430.          'SunFA_Tilde' => 'dead_tilde',
  2431.          'dead_breve' => 'dead_breve',
  2432.          'dead_diaeresis' => 'dead_diaeresis',
  2433.          'SunFA_Diaeresis' => 'dead_diaeresis', # Is this recognised by X ?
  2434.          'dead_doubleacute' => 'dead_doubleacute',
  2435.          'dead_caron' => 'dead_caron',
  2436.          'dead_V' => 'dead_caron', # Is this correct?
  2437.          'dead_cedilla' => 'dead_cedilla',
  2438.          'SunFA_Cedilla' => 'dead_cedilla', # Is this recognised by X ?
  2439.          'dead_ogonek' => 'dead_ogonek',
  2440. # Dead symbols with no support in the kernel
  2441.          'dead_macron' => '005f',         # underscore
  2442.          'dead_abovedot' => '002e',       # period
  2443.          'dead_abovering' => '00b0',      # degree
  2444.          'dead_stroke' => '002d',         # hyphen
  2445.          'dead_belowdot' => '0323',       # ???? Vietnamese or Romanian cedilla
  2446.          'dead_hook' => '0309',           # ???? Vietnamese
  2447.          'dead_belowcomma' => 'VoidSymbol',
  2448.          'dead_currency' => 'VoidSymbol',
  2449.          'dead_doublegrave' => 'VoidSymbol',
  2450.          'dead_invertedbreve' => 'VoidSymbol',
  2451.          'dead_iota' => '03b9',           # ???? Greek
  2452.          'dead_horn' => '031b',           # ???? Greek
  2453.          'dead_psili' => 'VoidSymbol',    # ???? Greek
  2454.          'dead_dasia' => 'VoidSymbol',    # ???? Greek
  2455. # Modifiers
  2456.          'Multi_key' => 'Compose',
  2457.          'Mode_switch' => 'ShiftL',
  2458.          'script_switch' => 'VoidSymbol',
  2459.          'Shift_L' => 'Shift',
  2460.          'Shift_R' => 'Shift',
  2461.          'Control_L' => 'Control',
  2462.          'Control_R' => 'Control',
  2463.          'Caps_Lock' => 'Caps_Lock',
  2464.          'Shift_Lock' => 'Shift_Lock',
  2465.          'Meta_L' => 'Alt',
  2466.          'Meta_R' => 'Alt',
  2467.          'Alt_L' => 'Alt',
  2468.          'Alt_R' => 'Alt',
  2469.          'Super_L' => 'Alt',
  2470.          'Super_R' => 'Alt',
  2471.          'Hyper_L' => 'Alt',
  2472.          'Hyper_R' => 'Alt',
  2473.          'ISO_Lock' => 'Caps_Lock',
  2474.          'ISO_Level2_Latch' => 'Shift',
  2475.          'ISO_Level3_Shift' => 'AltGr',
  2476.          'ISO_Level3_Latch' => 'AltGr',
  2477.          'ISO_Level3_Lock' => 'AltGr_Lock',
  2478.          'ISO_Level5_Shift' => 'AltGr',
  2479.          'ISO_Level5_Latch' => 'AltGr',
  2480.          'ISO_Level5_Lock' => 'AltGr_Lock',
  2481.          'ISO_Group_Shift' => 'ShiftL',
  2482.          'ISO_Group_Latch' => 'ShiftL',
  2483.          'ISO_Group_Lock' => 'ShiftL_Lock',
  2484.          'ISO_Next_Group' => 'ShiftL_Lock',
  2485.          'ISO_Next_Group_Lock' => 'ShiftL_Lock',
  2486.          'ISO_Prev_Group' => 'ShiftL_Lock',
  2487.          'ISO_Prev_Group_Lock' => 'ShiftL_Lock',
  2488.          'ISO_First_Group' => 'ShiftL_Lock',
  2489.          'ISO_First_Group_Lock' => 'ShiftL_Lock',
  2490.          'ISO_Last_Group' => 'ShiftL_Lock',
  2491.          'ISO_Last_Group_Lock' => 'ShiftL_Lock',
  2492. # Other symbols
  2493.          'NoAction' => 'NoSymbol', # Is this recognised by X ?
  2494.          'nosymbol' => 'NoSymbol', # Is this recognised by X ?
  2495.          'Nosymbol' => 'NoSymbol', # Is this recognised by X ?
  2496.          'noSymbol' => 'NoSymbol', # Is this recognised by X ?
  2497.          'NoSymbol' => 'NoSymbol',
  2498.          'any' => 'NoSymbol', # Is this recognised by X ?
  2499.          'VoidSymbol' => 'VoidSymbol',
  2500.          'voidsymbol' => 'VoidSymbol', # Is this recognised by X ?
  2501.          'ISO_Left_Tab' => 'Tab',
  2502.          'Clear' => 'VoidSymbol',
  2503.          'Pause' => 'Pause',
  2504.          'Scroll_Lock' => 'Scroll_Lock',
  2505.          'Sys_Req' => 'Last_Console',
  2506.          'Delete' => 'Remove',
  2507.          'Codeinput' => 'VoidSymbol',
  2508.          'SingleCandidate' => 'VoidSymbol',
  2509.          'MultipleCandidate' => 'VoidSymbol',
  2510.          'PreviousCandidate' => 'VoidSymbol',
  2511.          'Home' => 'Home',
  2512.          'Left' => 'Left',
  2513.          'Up' => 'Up',
  2514.          'Right' => 'Right',
  2515.          'Down' => 'Down',
  2516.          'Prior' => 'Prior',
  2517.          'Page_Up' => 'PageUp',
  2518.          'Next' => 'Next',
  2519.          'Page_Down' => 'PageDown',
  2520.          'End' => 'End',
  2521.          'Begin' => 'VoidSymbol',
  2522.          'Select' => 'Select',
  2523.          'Print' => 'Control_backslash',
  2524.          'Execute' => 'VoidSymbol',
  2525.          'Insert' => 'Insert',
  2526.          'Undo' => 'VoidSymbol',
  2527.          'Redo' => 'VoidSymbol',
  2528.          'Menu' => 'VoidSymbol',
  2529.          'Find' => 'Find',
  2530.          'Cancel' => 'VoidSymbol',
  2531.          'Help' => 'Help',
  2532.          'Break' => 'Break',
  2533.          'Num_Lock' => 'Num_Lock',
  2534.          'F1' => 'F1',
  2535.          'F2' => 'F2',
  2536.          'F3' => 'F3',
  2537.          'F4' => 'F4',
  2538.          'F5' => 'F5',
  2539.          'F6' => 'F6',
  2540.          'F7' => 'F7',
  2541.          'F8' => 'F8',
  2542.          'F9' => 'F9',
  2543.          'F10' => 'F10',
  2544.          'F11' => 'F11',
  2545.          'L1' => 'F11',
  2546.          'F12' => 'F12',
  2547.          'L2' => 'F12',
  2548.          'F13' => 'F13',
  2549.          'L3' => 'F13',
  2550.          'F14' => 'F14',
  2551.          'L4' => 'F14',
  2552.          'F15' => 'F15',
  2553.          'L5' => 'F15',
  2554.          'F16' => 'F16',
  2555.          'L6' => 'F16',
  2556.          'F17' => 'F17',
  2557.          'L7' => 'F17',
  2558.          'F18' => 'F18',
  2559.          'L8' => 'F18',
  2560.          'F19' => 'F19',
  2561.          'L9' => 'F19',
  2562.          'F20' => 'F20',
  2563.          'L10' => 'F20',
  2564.          'F21' => 'F21',
  2565.          'R1' => 'F21',
  2566.          'F22' => 'F22',
  2567.          'R2' => 'F22',
  2568.          'F23' => 'F23',
  2569.          'R3' => 'F23',
  2570.          'F24' => 'F24',
  2571.          'R4' => 'F24',
  2572.          'F25' => 'F25',
  2573.          'R5' => 'F25',
  2574.          'F26' => 'F26',
  2575.          'R6' => 'F26',
  2576.          'F27' => 'F27',
  2577.          'R7' => 'F27',
  2578.          'F28' => 'F28',
  2579.          'R8' => 'F28',
  2580.          'F29' => 'F29',
  2581.          'R9' => 'F29',
  2582.          'F30' => 'F30',
  2583.          'R10' => 'F30',
  2584.          'F31' => 'F31',
  2585.          'R11' => 'F31',
  2586.          'F32' => 'F32',
  2587.          'R12' => 'F32',
  2588.          'F33' => 'F33',
  2589.          'R13' => 'F33',
  2590.          'F34' => 'F34',
  2591.          'R14' => 'F34',
  2592.          'F35' => 'F35',
  2593.          'R15' => 'F35',
  2594.          'Terminate_Server' => 'VoidSymbol',
  2595.          'Pointer_EnableKeys' => 'VoidSymbol',
  2596.          'XF86_Switch_VT_1' => 'Console_1',
  2597.          'XF86_Switch_VT_2' => 'Console_2',
  2598.          'XF86_Switch_VT_3' => 'Console_3',
  2599.          'XF86_Switch_VT_4' => 'Console_4',
  2600.          'XF86_Switch_VT_5' => 'Console_5',
  2601.          'XF86_Switch_VT_6' => 'Console_6',
  2602.          'XF86_Switch_VT_7' => 'Console_7',
  2603.          'XF86_Switch_VT_8' => 'Console_8',
  2604.          'XF86_Switch_VT_9' => 'Console_9',
  2605.          'XF86_Switch_VT_10' => 'Console_10',
  2606.          'XF86_Switch_VT_11' => 'Console_11',
  2607.          'XF86_Switch_VT_12' => 'Console_12',
  2608.          'XF86_ClearGrab' => 'VoidSymbol',
  2609.          'XF86_Ungrab' => 'VoidSymbol',
  2610.          'XF86_Next_VMode' => 'VoidSymbol',
  2611.          'XF86_Prev_VMode' => 'VoidSymbol',
  2612.          'XF86Copy' => 'VoidSymbol',
  2613.          'XF86Cut' => 'VoidSymbol',
  2614.          'XF86Paste' => 'VoidSymbol',
  2615.          'XF86AudioLowerVolume' => 'VoidSymbol',
  2616.          'XF86AudioRaiseVolume' => 'VoidSymbol',
  2617.          'XF86AudioMute' => 'VoidSymbol',
  2618.          'XF86PowerOff' => 'VoidSymbol',
  2619.          'XF86AudioForward' => 'VoidSymbol',
  2620.          'XF86AudioMedia' => 'VoidSymbol',
  2621.          'XF86AudioNext' => 'VoidSymbol',
  2622.          'XF86AudioPause' => 'VoidSymbol',
  2623.          'XF86AudioPlay' => 'VoidSymbol',
  2624.          'XF86AudioPrev' => 'VoidSymbol',
  2625.          'XF86AudioRecord' => 'VoidSymbol',
  2626.          'XF86AudioRewind' => 'VoidSymbol',
  2627.          'XF86AudioStop' => 'VoidSymbol',
  2628.          'XF86Back' => 'VoidSymbol',
  2629.          'XF86Battery' => 'VoidSymbol',
  2630.          'XF86Bluetooth' => 'VoidSymbol',
  2631.          'XF86Calculator' => 'VoidSymbol',
  2632.          'XF86Close' => 'VoidSymbol',
  2633.          'XF86Display' => 'VoidSymbol',
  2634.          'XF86Documents' => 'VoidSymbol',
  2635.          'XF86DOS' => 'VoidSymbol',
  2636.          'XF86Eject' => 'VoidSymbol',
  2637.          'XF86Explorer' => 'VoidSymbol',
  2638.          'XF86Favorites' => 'VoidSymbol',
  2639.          'XF86Finance' => 'VoidSymbol',
  2640.          'XF86Forward' => 'VoidSymbol',
  2641.          'XF86HomePage' => 'VoidSymbol',
  2642.          'XF86KbdBrightnessDown' => 'VoidSymbol',
  2643.          'XF86KbdBrightnessUp' => 'VoidSymbol',
  2644.          'XF86KbdLightOnOff' => 'VoidSymbol',
  2645.          'XF86Launch1' => 'VoidSymbol',
  2646.          'XF86Launch2' => 'VoidSymbol',
  2647.          'XF86Launch3' => 'VoidSymbol',
  2648.          'XF86Launch4' => 'VoidSymbol',
  2649.          'XF86Mail' => 'VoidSymbol',
  2650.          'XF86MailForward' => 'VoidSymbol',
  2651.          'XF86MenuKB' => 'VoidSymbol',
  2652.          'XF86MonBrightnessDown' => 'VoidSymbol',
  2653.          'XF86MonBrightnessUp' => 'VoidSymbol',
  2654.          'XF86MyComputer' => 'VoidSymbol',
  2655.          'XF86New' => 'VoidSymbol',
  2656.          'XF86Phone' => 'VoidSymbol',
  2657.          'XF86Reload' => 'VoidSymbol',
  2658.          'XF86Reply' => 'VoidSymbol',
  2659.          'XF86RotateWindows' => 'VoidSymbol',
  2660.          'XF86Save' => 'VoidSymbol',
  2661.          'XF86ScreenSaver' => 'VoidSymbol',
  2662.          'XF86ScrollDown' => 'VoidSymbol',
  2663.          'XF86ScrollUp' => 'VoidSymbol',
  2664.          'XF86Search' => 'VoidSymbol',
  2665.          'XF86Send' => 'VoidSymbol',
  2666.          'XF86Shop' => 'VoidSymbol',
  2667.          'XF86Sleep' => 'VoidSymbol',
  2668.          'XF86Suspend' => 'VoidSymbol',
  2669.          'XF86Tools' => 'VoidSymbol',
  2670.          'XF86TouchpadToggle' => 'VoidSymbol',
  2671.          'XF86WakeUp' => 'VoidSymbol',
  2672.          'XF86WebCam' => 'VoidSymbol',
  2673.          'XF86WLAN' => 'VoidSymbol',
  2674.          'XF86WWW' => 'VoidSymbol',
  2675.          'XF86Xfer' => 'VoidSymbol',
  2676.          'braille_blank' => 'Brl_blank',
  2677.          'braille_dot_1' => 'Brl_dot1',
  2678.          'braille_dot_2' => 'Brl_dot2',
  2679.          'braille_dot_3' => 'Brl_dot3',
  2680.          'braille_dot_4' => 'Brl_dot4',
  2681.          'braille_dot_5' => 'Brl_dot5',
  2682.          'braille_dot_6' => 'Brl_dot6',
  2683.          'braille_dot_7' => 'Brl_dot7',
  2684.          'braille_dot_8' => 'Brl_dot8',
  2685.          'braille_dot_9' => 'Brl_dot9',
  2686.          'braille_dot_10' => 'Brl_dot10',
  2687. # I do not know the Unicodes of these
  2688.          '0x1000' => 'VoidSymbol', # Special symbol for X or syntax error?
  2689.          '0x13a4' => 'VoidSymbol', # Special symbol for X or syntax error?
  2690.          '0xfe11' => 'VoidSymbol', # Special symbol for X or syntax error?
  2691.          'leftcaret' => 'VoidSymbol', # Is this recognised by X ?
  2692.          'guj_rra' => 'VoidSymbol', # Is this recognised by X ?
  2693.          'guj_nnna' => 'VoidSymbol', # Is this recognised by X ?
  2694.          'guj_llla' => 'VoidSymbol', # Is this recognised by X ?
  2695.          'gur_visarga' => 'VoidSymbol', # Is this recognised by X ?
  2696.          'gur_v_r' => 'VoidSymbol', # Is this recognised by X ?
  2697.          'gur_v_r_s' => 'VoidSymbol', # Is this recognised by X ?
  2698.          'Eisu_toggle' => 'VoidSymbol', # Is this recognised by X ?
  2699.          'Zenkaku_Hankaku' => 'VoidSymbol', # Is this recognised by X ?
  2700.          'Kanji' => 'VoidSymbol', # Is this recognised by X ?
  2701.          'Hangul' => 'VoidSymbol', # Is this recognised by X ?
  2702.          'Hangul_Hanja' => 'VoidSymbol', # Is this recognised by X ?
  2703.          'Henkan' => 'VoidSymbol',
  2704.          'Hiragana' => 'VoidSymbol',
  2705.          'Hiragana_Katakana' => 'VoidSymbol',
  2706.          'Katakana' => 'VoidSymbol',
  2707.          'Muhenkan' => 'VoidSymbol',
  2708. # XFree86 does not recognise these
  2709.          'SunAudioLowerVolume' => 'VoidSymbol',
  2710.          'SunAudioRaiseVolume' => 'VoidSymbol',
  2711.          'SunAudioMute' => 'VoidSymbol',
  2712.          'SunCopy' => 'VoidSymbol',
  2713.          'SunCut' => 'VoidSymbol',
  2714.          'SunPaste' => 'VoidSymbol',
  2715.          'SunAgain' => 'VoidSymbol',
  2716.          'SunUndo' => 'VoidSymbol',
  2717.          'SunFind' => 'VoidSymbol',
  2718.          'SunStop' => 'VoidSymbol',
  2719.          'SunF36' => 'VoidSymbol',
  2720.          'SunF37' => 'VoidSymbol',
  2721.          'SunFront' => 'VoidSymbol',
  2722.          'SunOpen' => 'VoidSymbol',
  2723.          'SunPowerSwitch' => 'VoidSymbol',
  2724.          'SunPowerSwitchShift' => 'VoidSymbol',
  2725.          'SunProps' => 'VoidSymbol',
  2726.          'SunSys_Req' => 'VoidSymbol',
  2727.          'SunVideoDegauss' => 'VoidSymbol',
  2728.          'SunVideoLowerBrightness' => 'VoidSymbol',
  2729.          'SunVideoRaiseBrightness' => 'VoidSymbol',
  2730.         );
  2731.  
  2732.     if ($compact) {
  2733.         $xkbsym_table{'Mode_switch'} = 'AltGr';
  2734.         $xkbsym_table{'ISO_Group_Shift'} = 'AltGr';
  2735.         $xkbsym_table{'ISO_Group_Latch'} = 'AltGr';
  2736.         $xkbsym_table{'ISO_Group_Lock'} = 'AltGr_Lock';
  2737.         $xkbsym_table{'ISO_Next_Group'} = 'AltGr_Lock';
  2738.         $xkbsym_table{'ISO_Next_Group_Lock'} = 'AltGr_Lock';
  2739.         $xkbsym_table{'ISO_Prev_Group'} = 'AltGr_Lock';
  2740.         $xkbsym_table{'ISO_Prev_Group_Lock'} = 'AltGr_Lock';
  2741.         $xkbsym_table{'ISO_First_Group'} = 'AltGr_Lock';
  2742.         $xkbsym_table{'ISO_First_Group_Lock'} = 'AltGr_Lock';
  2743.         $xkbsym_table{'ISO_Last_Group'} = 'AltGr_Lock';
  2744.         $xkbsym_table{'ISO_Last_Group_Lock'} = 'AltGr_Lock';
  2745.     }
  2746.     if ($backspace eq 'bs') {
  2747.         $xkbsym_table{'BackSpace'} = 'BackSpace';
  2748.         $xkbsym_table{'Delete'} = 'Delete';
  2749.     }
  2750. }
  2751.  
  2752. my $voidsymbol = $freebsd ? 'nop' : 'VoidSymbol';
  2753.  
  2754. my @controlsyms;
  2755. my @metasyms;
  2756. my @metacontrolsyms;
  2757. my %controlsyms_hash;
  2758.  
  2759. {
  2760.     if ($freebsd) {
  2761.  
  2762.         %controlsyms_hash = (
  2763.             'nul' => 0x00,
  2764.             'soh' => 0x01,
  2765.             'stx' => 0x02,
  2766.             'etx' => 0x03,
  2767.             'eot' => 0x04,
  2768.             'enq' => 0x05,
  2769.             'ack' => 0x06,
  2770.             'bel' => 0x07,
  2771.             'bs' => 0x08,
  2772.             'ht' => 0x09,
  2773.             'nl' => 0x0a,
  2774.             'vt' => 0x0b,
  2775.             'ff' => 0x0c,
  2776.             'cr' => 0x0d,
  2777.             'so' => 0x0e,
  2778.             'si' => 0x0f,
  2779.             'dle' => 0x10,
  2780.             'dc1' => 0x11,
  2781.             'dc2' => 0x12,
  2782.             'dc3' => 0x13,
  2783.             'dc4' => 0x14,
  2784.             'nak' => 0x15,
  2785.             'syn' => 0x16,
  2786.             'etb' => 0x17,
  2787.             'can' => 0x18,
  2788.             'em' => 0x19,
  2789.             'sub' => 0x1a,
  2790.             'esc' => 0x1b,
  2791.             'fs' => 0x1c,
  2792.             'gs' => 0x1d,
  2793.             'rs' => 0x1e,
  2794.             'us' => 0x1f,
  2795.             'del' => 0x7f,
  2796.             );
  2797.     } else {
  2798.         %controlsyms_hash = (
  2799.             'nul' => 0x00,
  2800.             'Control_a' => 0x01,
  2801.             'Control_b' => 0x02,
  2802.             'Control_c' => 0x03,
  2803.             'Control_d' => 0x04,
  2804.             'Control_e' => 0x05,
  2805.             'Control_f' => 0x06,
  2806.             'Control_g' => 0x07,
  2807.             'BackSpace' => 0x08,
  2808.             'Tab' => 0x09,
  2809.             'Linefeed' => 0x0a,
  2810.             'Control_k' => 0x0b,
  2811.             'Control_l' => 0x0c,
  2812.             'Return' => 0x0d,
  2813.             'Control_n' => 0x0e,
  2814.             'Control_o' => 0x0f,
  2815.             'Control_p' => 0x10,
  2816.             'Control_q' => 0x11,
  2817.             'Control_r' => 0x12,
  2818.             'Control_s' => 0x13,
  2819.             'Control_t' => 0x14,
  2820.             'Control_u' => 0x15,
  2821.             'Control_v' => 0x16,
  2822.             'Control_w' => 0x17,
  2823.             'Control_x' => 0x18,
  2824.             'Control_y' => 0x19,
  2825.             'Control_z' => 0x1a,
  2826.             'Escape' => 0x1b,
  2827.             'Control_backslash' => 0x1c,
  2828.             'Control_bracketright' => 0x1d,
  2829.             'Control_asciicircum' => 0x1e,
  2830.             'Control_underscore' => 0x1f,
  2831.             'Delete' => 0x7f,
  2832.             );
  2833.     }        
  2834.     for my $special (keys %controlsyms_hash) {
  2835.         $controlsyms[$controlsyms_hash{$special}] = $special;
  2836.     }
  2837.     for my $code (0 .. 255) {
  2838.         if (! defined $controlsyms[$code]) {
  2839.             if ($code >= 64 && $code <= 127
  2840.                 && defined (my $special = $controlsyms[$code % 32])) {
  2841.                 $controlsyms[$code] = $special;
  2842.             } else {
  2843.                 $controlsyms[$code] = $voidsymbol;
  2844.             }
  2845.         }
  2846.     }
  2847. # Ctrl + BS = DEL, Ctrl + DEL = BS
  2848.     if ($freebsd) {
  2849.         $controlsyms[0x08] = 'del';
  2850.         $controlsyms[0x7f] = 'bs';
  2851.     } else {
  2852.         $controlsyms[0x08] = 'Delete';
  2853.         $controlsyms[0x7f] = 'BackSpace';
  2854.     }
  2855. # Some particularities of FreeBSD and Linux
  2856.     if ($freebsd) {
  2857.         $controlsyms[0x0d] = 'nl';                     # Ctrl+m = ^J
  2858.         $controlsyms[0x20] = 'nul';                    # Ctrl+space = ^@
  2859.         $controlsyms[0x3f] = 'del';                    # Ctrl+? = ^?
  2860.     } else {
  2861.         $controlsyms[0x0d] = 'Control_m';              # I don't know
  2862.         $controlsyms[0x20] = 'nul';                    # Ctrl+space = ^@
  2863.         $controlsyms[0x2e] = 'Compose';                # Ctrl+. = Compose
  2864.         $controlsyms[0x3f] = 'Delete';                 # Ctrl+? = ^?
  2865. # I suppose these are not necessary:
  2866.         # $controlsyms[0x27] = 'Control_g';              # Ctrl+' = ^G
  2867.         # $controlsyms[0x32] = 'nul';                    # 2
  2868.         # $controlsyms[0x33] = 'Escape';                 # 3
  2869.         # $controlsyms[0x34] = 'Control_backslash';      # 4
  2870.         # $controlsyms[0x35] = 'Control_bracketright';   # 5
  2871.         # $controlsyms[0x36] = 'Control_asciicircum';    # 6
  2872.         # $controlsyms[0x37] = 'Control_underscore';     # 7
  2873.         # $controlsyms[0x38] = 'Delete';                 # 8
  2874.     }
  2875.  
  2876.     my %metasyms_hash = (
  2877.     ' ' => 'space',
  2878.     '`' => 'grave',
  2879.     '^' => 'asciicircum',
  2880.     '~' => 'asciitilde',
  2881.     '<' => 'less',
  2882.     '=' => 'equal',
  2883.     '>' => 'greater',
  2884.     '|' => 'bar',
  2885.     '_' => 'underscore',
  2886.     '-' => 'minus',
  2887.     ',' => 'comma',
  2888.     ';' => 'semicolon',
  2889.     ':' => 'colon',
  2890.     '!' => 'exclam',
  2891.     '?' => 'question',
  2892.     '/' => 'slash',
  2893.     '.' => 'period',
  2894.     '\'' => 'apostrophe',
  2895.     '"' => 'quotedbl',
  2896.     '(' => 'parenleft',
  2897.     ')' => 'parenright',
  2898.     '[' => 'bracketleft',
  2899.     ']' => 'bracketright',
  2900.     '{' => 'braceleft',
  2901.     '}' => 'braceright',
  2902.     '@' => 'at',
  2903.     '$' => 'dollar',
  2904.     '*' => 'asterisk',
  2905.     '\\' => 'backslash',
  2906.     '&' => 'ampersand',
  2907.     '#' => 'numbersign',
  2908.     '%' => 'percent',
  2909.     '+' => 'plus',
  2910.     '0' => 'zero',
  2911.     '1' => 'one',
  2912.     '2' => 'two',
  2913.     '3' => 'three',
  2914.     '4' => 'four',
  2915.     '5' => 'five',
  2916.     '6' => 'six',
  2917.     '7' => 'seven',
  2918.     '8' => 'eight',
  2919.     '9' => 'nine',
  2920.     chr(0x08) => 'BackSpace',
  2921.     chr(0x09) => 'Tab',
  2922.     chr(0x0a) => 'Linefeed',
  2923.     chr(0x0d) => 'Control_m',
  2924.     chr(0x1b) => 'Escape',
  2925.         chr(0x1c) => 'Control_backslash',
  2926.     chr(0x7f) => 'Delete',
  2927.     );
  2928.     
  2929.     for my $code (0 .. 255) {
  2930.     my $sym = chr($code);
  2931.     if (defined (my $special = $metasyms_hash{$sym})) {
  2932.         $sym = $special;
  2933.     }
  2934.     $metasyms[$code] = "Meta_". $sym;
  2935.     }
  2936.  
  2937.     for my $code (0 .. 255) {
  2938.     my $control = $controlsyms[$code];
  2939.     if ($control eq 'Compose') {
  2940.         $metacontrolsyms[$code] = 'Compose';
  2941.     } elsif ($control eq 'Return') {
  2942.         $metacontrolsyms[$code] = 'Meta_Control_m';
  2943.     } elsif ($control eq 'NoSymbol') {
  2944.         $metacontrolsyms[$code] = 'NoSymbol';
  2945.     } elsif ($control eq 'VoidSymbol') {
  2946.         $metacontrolsyms[$code] = 'VoidSymbol';
  2947.     } else {
  2948.         $metacontrolsyms[$code] = 'Meta_'. $control;
  2949.     }
  2950.     }
  2951. }
  2952.  
  2953. ############ GLOBAL FUNCTIONS #########################################
  2954.  
  2955. # Looks for $_[0] in the known directories and returns ready to use
  2956. # file name
  2957. sub xfilename {
  2958.     my $file = $_[0];
  2959.     (my $base = $file) =~ s/.*\/(.+)/$1/;
  2960.     for my $dir (@xdirs) {
  2961.     if (-f "$dir/$file") {
  2962.         return "$dir/$file";
  2963.     }
  2964.     if (-f "$dir/$base") {
  2965.         return "$dir/$base";
  2966.     }
  2967.     }
  2968.     die "$0: Can not find file \"$file\" in any known directory\n";
  2969. }
  2970.  
  2971. ########### READ THE RULES FILE #######################################
  2972.  
  2973. # The string $_[0] matches the pattern $_[1]. 
  2974. # The pattern may be "*", a variable name, or a plain string.
  2975. # If the string is 'OPTIONS' then match the pattern against any of the
  2976. # options from @options.
  2977. sub matches_pattern {
  2978.     my ($string, $pattern) = @_;
  2979.     if ($string eq 'OPTIONS') {
  2980.     for my $option (@options) {
  2981.         next if ($option eq '');
  2982.         if ($pattern eq $option) {
  2983.         return 1;
  2984.         }
  2985.     }
  2986.     } else {
  2987.     if ($pattern eq '*') {
  2988.         return $string ne '';
  2989.     }
  2990.     if ($pattern =~ /^\$([a-zA-Z0-9_]+)$/) {
  2991.         for my $member (@{$rules_variables{$1}}) {
  2992.         if ($string eq $member) {
  2993.             return 1;
  2994.         }
  2995.         }
  2996.         return 0;
  2997.     }
  2998.     if ($string eq $pattern) {
  2999.         return 1;
  3000.     }
  3001.     }
  3002.     return 0;
  3003. }
  3004.  
  3005. if (@layouts) {
  3006.     for my $i (0 .. $#layouts) {
  3007.     if (! defined $variants[$i]) {
  3008.         $variants[$i] = '';
  3009.     }
  3010.     }
  3011.     my $rules_keycodes;
  3012.     my $rules_symbols;
  3013.     open (RULES, xfilename ("rules/$rules"))
  3014.     or die "$0: ". xfilename ("rules/$rules") .": $!\n";
  3015.     my $oldline = '';
  3016.     my @antecedents;
  3017.     my @consequents;
  3018.     my $match_found = 0;
  3019.     while (<RULES>) {
  3020.     next if (/^\s*\/\//);
  3021.     next if (/^\s*$/);
  3022.     chomp;
  3023.     s/^\s*//;
  3024.     s/\s+/ /g;
  3025.     if ($oldline) {
  3026.         $_ = $oldline . $_;
  3027.         $oldline = '';
  3028.     }
  3029.     if (s/\\$/ /) {
  3030.         $oldline = $_;
  3031.         next;
  3032.     }
  3033.     if (/^! ?\$([a-zA-Z0-9_]+) ?= ?(.+)$/) {
  3034.         $rules_variables{$1} = [ split ' ', $2 ];
  3035.         next;
  3036.     }
  3037.     if (/^! ?(.+)= ?(.+)$/) {
  3038.         @antecedents = split ' ', $1;
  3039.         @consequents = split ' ', $2;
  3040.         foreach my $i (0 .. $#antecedents) {
  3041.         if ($antecedents[$i] eq 'model') {
  3042.             $antecedents[$i] = $model;
  3043.         } elsif ($antecedents[$i] eq 'layout' && @layouts == 1) {
  3044.             $antecedents[$i] = $layouts[0];
  3045.         } elsif ($antecedents[$i] =~ /layout\[([1-4])\]/) {
  3046.             if (@layouts > 1) {
  3047.             $antecedents[$i] = $layouts[$1 - 1];
  3048.             } else {
  3049.             $antecedents[$i] = '';
  3050.             }
  3051.         } elsif ($antecedents[$i] eq 'variant' && @variants == 1) {
  3052.             $antecedents[$i] = $variants[0];
  3053.         } elsif ($antecedents[$i] =~ /variant\[([1-4])\]/) {
  3054.             if (@variants > 1) {
  3055.             $antecedents[$i] = $variants[$1 - 1];
  3056.             } else {
  3057.             $antecedents[$i] = '';
  3058.             }
  3059.         } elsif ($antecedents[$i] eq 'option') {
  3060.             $antecedents[$i] = 'OPTIONS';
  3061.         } elsif ($antecedents[$i] eq 'layout'
  3062.              || $antecedents[$i] eq 'variant') {
  3063.             $antecedents[$i] = '';
  3064.         } else {
  3065.                     warning "Unknown name \"$antecedents[$i]\" in the following line in \"rules/$rules\":\n";
  3066.                     warning "$_\n";
  3067.             $antecedents[$i] = '';
  3068.         }
  3069.         if (! defined $antecedents[$i]) {
  3070.             $antecedents[$i] = '';
  3071.         }
  3072.         }
  3073.         $match_found = 0;
  3074.         next;
  3075.     }
  3076.     if (/^(.+)= ?(.+)$/) {
  3077.         next if ($match_found);
  3078.         my @antecedent_patterns = split ' ', $1;
  3079.         my $consequent_str = $2;
  3080.         if (@antecedent_patterns != @antecedents ) {
  3081.         warning "Bad number of antecedents in the following line in \"rules/$rules\":\n";
  3082.                 warning "$_\n";
  3083.                 next;
  3084.             }
  3085.         my $matches = 1;
  3086.         for my $i (0 .. $#antecedents) {
  3087.         if (! matches_pattern ($antecedents[$i], 
  3088.                        $antecedent_patterns[$i])) {
  3089.             $matches = 0;
  3090.             last;
  3091.         }
  3092.         }
  3093.         if ($matches) {
  3094.         $match_found = $antecedents[0] ne 'OPTIONS';
  3095.         my @consequent_values = split ' ', $2;
  3096.                 if (@consequent_values != @consequents) {
  3097.                     warning "Bad number of consequents in the following line in \"rules/$rules\":\n";
  3098.                     warning "$_\n";
  3099.                 }
  3100.         for my $i (0 .. $#consequents) {
  3101.                     # The purpose of the semicolons is to make %(v) and %_v
  3102.                     # empty strings if %v is an empty string
  3103.             $consequent_values[$i] =~ s/%\(/\(;%/g;
  3104.             $consequent_values[$i] =~ s/%_/_;%/g;
  3105.             $consequent_values[$i] =~ s/(%[lvm](\[[1-4]\])?)/$1;/g;
  3106.             $consequent_values[$i] =~ s/%m/$model/g;
  3107.             $consequent_values[$i] =~ s/%l\[1\]/$layouts[0]/g;
  3108.             $consequent_values[$i] =~ s/%l\[2\]/$layouts[1]/g;
  3109.             $consequent_values[$i] =~ s/%l\[3\]/$layouts[2]/g;
  3110.             $consequent_values[$i] =~ s/%l\[4\]/$layouts[3]/g;
  3111.             $consequent_values[$i] =~ s/%l/$layouts[0]/g;
  3112.             $consequent_values[$i] =~ s/%v\[1\]/$variants[0]/g;
  3113.             $consequent_values[$i] =~ s/%v\[2\]/$variants[1]/g;
  3114.             $consequent_values[$i] =~ s/%v\[3\]/$variants[2]/g;
  3115.             $consequent_values[$i] =~ s/%v\[4\]/$variants[3]/g;
  3116.             $consequent_values[$i] =~ s/%v/$variants[0]/g;
  3117.             $consequent_values[$i] =~ s/\(;;\)//g;
  3118.             $consequent_values[$i] =~ s/_;;//g;
  3119.             $consequent_values[$i] =~ s/;//g;
  3120.             if ($consequent_values[$i] =~ /^\+/) {
  3121.             if ($consequents[$i] eq 'keycodes') {
  3122.                 $rules_keycodes = $rules_keycodes .
  3123.                 $consequent_values[$i];
  3124.             } elsif ($consequents[$i] eq 'symbols') {
  3125.                 $rules_symbols = $rules_symbols .
  3126.                 $consequent_values[$i];
  3127.             }
  3128.             } else {
  3129.             if ($consequents[$i] eq 'keycodes') {
  3130.                 if (! $rules_keycodes) {
  3131.                 $rules_keycodes = $consequent_values[$i];
  3132.                 }
  3133.             } elsif ($consequents[$i] eq 'symbols') {
  3134.                 if (! $rules_symbols) {
  3135.                 $rules_symbols = $consequent_values[$i];
  3136.                 }
  3137.             }
  3138.             }
  3139.         }
  3140.         }
  3141.         next;
  3142.     }    
  3143.     warning "Syntax error in the following line in \"rules/$rules\":\n";
  3144.         warning "$_\n";
  3145.         die;
  3146.     }
  3147.     close RULES;
  3148.  
  3149.     if ($verbosity >= 1) {
  3150.     print STDERR  "Acording to the rules file:\n"
  3151.         ." keycodes = $rules_keycodes\n"
  3152.         ." symbols = $rules_symbols\n";
  3153.     }
  3154.  
  3155.     if (! $keycodes) {
  3156.     $keycodes = $rules_keycodes;
  3157.     }
  3158.     if (! $symbols) {
  3159.     $symbols = $rules_symbols;
  3160.     }
  3161. }
  3162.  
  3163. if (! $keycodes) {
  3164.     die "$0: No keycodes, nor layout specified\n";
  3165. }
  3166. if (! $symbols) {
  3167.     die "$0: No symbols, nor layout specified\n";
  3168. }
  3169.  
  3170. ########### COMPUTE ARCH ###########################################
  3171.  
  3172. if ($keycodes =~ /(^|\+|\|)macintosh\(old\)($|\+|\|)/) {
  3173.     $arch = 'macintosh';
  3174. } elsif ($keycodes =~ /(^|\+|\|)ataritt(\([^\)]*\))?($|\+|\|)/) {
  3175.     $arch = 'ataritt';
  3176. } elsif ($keycodes =~ /(^|\+|\|)amiga(\([^\)]*\))?($|\+|\|)/) {
  3177.     $arch = 'amiga';
  3178. } elsif ($keycodes =~ /(^|\+|\|)sun(\(type[45][^\)]*\))?($|\+|\|)/) {
  3179.     $arch = 'sun';
  3180. } elsif ($keycodes =~ /(^|\+|\|)evdev(\([^\)]*\))?($|\+|\|)/) {
  3181.     $arch = 'evdev';
  3182. }
  3183.  
  3184. ########### READ ACM ###############################################
  3185.  
  3186. if ($charmap) {
  3187.     for my $acmfile ("$installdir/share/consoletrans/${charmap}",
  3188.                      "$installdir/share/consoletrans/${charmap}.gz",
  3189.                      "$installdir/share/consoletrans/${charmap}.acm",
  3190.                      "$installdir/share/consoletrans/${charmap}.acm.gz",
  3191.                      "/usr/share/consoletrans/${charmap}",
  3192.                      "/usr/share/consoletrans/${charmap}.gz",
  3193.                      "/usr/share/consoletrans/${charmap}.acm",
  3194.                      "/usr/share/consoletrans/${charmap}.acm.gz",
  3195.                      "${charmap}") {
  3196.     if (-f $acmfile) {
  3197.         $acm = $acmfile;
  3198.         last;
  3199.     }
  3200.     }
  3201.     (-f $acm) or die "$0: no ACM for ${charmap} exists\n";
  3202.     if ($acm =~ /gz$/) {
  3203.     open (ACM, '-|:utf8', "zcat $acm") or die "$0: $acm: $!\n";
  3204.     } else {
  3205.     open (ACM, '<:utf8', $acm) or die "$0: $acm: $!\n";
  3206.     }
  3207.     while (<ACM>) {
  3208.     s/\#.*//;
  3209.     chomp;
  3210.     next unless (/[^\s]/);
  3211.     if (/^\s*0x([0-9a-fA-F]{1,2})\s+\'([^\']+)\'\s*$/) {
  3212.         my $uni = ord ($2);
  3213.         my $c = hex ($1);
  3214.         $acmtable{$uni} = $c;
  3215.     } else {
  3216.         die "$0: Syntax error in ACM file: $_\n";
  3217.     }
  3218.     }
  3219.     close ACM;
  3220. }
  3221.  
  3222. ########### PARSING ###############################################
  3223.  
  3224. # Report a syntax error in $filename. $_[0] should describe what was
  3225. # expected at $stream.
  3226. sub syntax_error {
  3227.     die "$0: instead of \"". (substr ($stream, 0, 50))
  3228.     ."\" in $filename expected $_[0].\n";
  3229. }
  3230.  
  3231. # Opens the text file $_[0], reads it and saves its contents in $stream
  3232. # The comments are removed, all new lines are replaced by spaces and
  3233. # all redundant spaces are removed.
  3234. sub file_to_string {
  3235.     my $file = $_[0];
  3236.     my $string = '';
  3237.     open (FILE, "$file") or die "$0: $file: $!\n";
  3238.     while (<FILE>) {
  3239.     chomp;
  3240.     s{//.*}{};
  3241.     s{\#.*}{};
  3242.     $string = $string . $_ .' ';
  3243.     }
  3244.     close FILE;
  3245.     
  3246.     my $normalized = '';
  3247.     my $final_letter = 0;
  3248.     while ($string) {
  3249.     if ($string =~ s/^\s+// && $final_letter && $string =~ /^[a-zA-Z0-9_]/) {
  3250.         $normalized = $normalized .' ';
  3251.         $final_letter = 0;
  3252.     }
  3253.     if ($string =~ s/^([^\"\s]+)//) {
  3254.         $normalized = $normalized . $1;
  3255.         $final_letter = ($1 =~ /[a-zA-Z0-9_]$/);
  3256.         next;
  3257.     }
  3258.     if ($string =~ s/^(\"[^\"]*(\"|$))//) {
  3259.         $normalized = $normalized . $1;
  3260.         $final_letter = 0;
  3261.         if ($2 ne '"') {
  3262.         die "$0: missing quote in ". (substr ($1, 0, 50)) ."...\n";
  3263.         }
  3264.         next;
  3265.     }
  3266.     (! $string ) or die "Internal error";
  3267.     }
  3268.     $stream = $normalized;
  3269. }
  3270.  
  3271. # removes from $stream initial sequence of xkb flags (default, partial,
  3272. # hidden, etc.) Returns true if the "default" flag was among them.
  3273. sub xkb_flags {
  3274.     my $default = 0;
  3275.     while ($stream =~ s/^(default|partial|hidden
  3276.               |alphanumeric_keys|modifier_keys
  3277.               |keypad_keys|function_keys
  3278.               |alternate_group)\s?(.*)/$2/ix) {
  3279.     $default = 1 if ($1 =~ /default/i);
  3280.     }
  3281.     return $default;
  3282. }
  3283.  
  3284. # Removes and returns identifier from $stream. 
  3285. sub xkb_identifier {
  3286.     if ($stream =~ s/^([a-zA-Z0-1_]+) ?(.*)/$2/) {
  3287.     return $1;
  3288.     } else {
  3289.     syntax_error "identifier";
  3290.     }
  3291. }
  3292.  
  3293. # Removes and returns a string from $stream.
  3294. sub xkb_string {
  3295.     if ($stream =~ /^\"([^\"]*)\"(.*)/) {
  3296.     $stream = $2;
  3297.     return $1;
  3298.     } else {
  3299.     syntax_error "string";
  3300.     }
  3301. }
  3302.  
  3303. # Removes an include method name from $stream and returns $alternate_method,
  3304. # $augment_method, $replace_method, or $override_method.  If $stream
  3305. # does not start with a method name, return the default method (i.e. $method)
  3306. sub xkb_method {
  3307.     if ($stream =~ s/^alternate ?(.*)/$1/i) {
  3308.     return $alternate_method;
  3309.     } elsif ($stream =~ s/^augment ?(.*)/$1/i) {
  3310.     return $augment_method;
  3311.     } elsif ($stream =~ s/^replace ?(.*)/$1/i) {
  3312.     return $replace_method;
  3313.     } elsif ($stream =~ s/^override ?(.*)/$1/i) {
  3314.     return $override_method;
  3315.     } else {
  3316.     return $method;
  3317.     }
  3318. }
  3319.  
  3320. # If $stream starts with an include statement - process it and return true.
  3321. # Otherwise return false. $_[0] is the file type ("symbols" or "keycodes")
  3322. sub xkb_include {
  3323.     my $file_type = $_[0];
  3324.     if ($stream =~ s/^(include|replace|augment|override)\"([^\"]*)\";?
  3325.                         (.*)/$3/ix) {
  3326.     my $method_name = $1;
  3327.     my $include_request = $2;
  3328.     if ($method != $ignore_method) {
  3329.         my $oldmethod = $method;
  3330.         if ($method_name =~ /replace/i) {
  3331.         $method = $replace_method;
  3332.         } elsif ($method_name =~ /augment/i) {
  3333.         $method = $augment_method;
  3334.         } elsif ($method_name =~ /override/i) {
  3335.         $method = $override_method;
  3336.         }
  3337.         &include_xkb_file ($file_type, $include_request);
  3338.         $method = $oldmethod;
  3339.     }
  3340.     return 1;
  3341.     } else {
  3342.     return 0;
  3343.     }
  3344. }
  3345.  
  3346. sub xkb_keycodes_definitions {
  3347.     my $oldmethod = $method;
  3348.     while ($stream) {
  3349.     $method = $oldmethod;
  3350.  
  3351.     if (xkb_include ('keycodes')) {
  3352.         next;
  3353.     }
  3354.  
  3355.     $method = xkb_method ();
  3356.     
  3357.     if ($stream =~ (s/^(minimum|maximum|indicator|virtual\sindicator)
  3358.             [^;]*;(.*)/$2/ix)) {
  3359.         next;
  3360.     }
  3361.  
  3362.     if ($stream =~ /^<([^>]*)>=/) {
  3363.         $stream =~ s/^<([^>]+)>=([0-9]*);(.*)/$3/
  3364.         or syntax_error "keycode definition";
  3365.         my $key = $1;
  3366.         my $code = $2;
  3367.         if ($method == $replace_method
  3368.         || $method == $override_method
  3369.         || ($method == $augment_method
  3370.             && ! defined $keycodes_table{$key})) {
  3371.         $keycodes_table{$key} = [ $code ];
  3372.         delete $aliases{$key};
  3373.         } elsif ($method == $alternate_method) {
  3374.         push @{$keycodes_table{$key}}, $code;
  3375.         }
  3376.         next;
  3377.     }
  3378.     if ($stream =~ /^alias/) {
  3379.         $stream =~ s/^alias<([^>]+)>=<([^>]+)>;(.*)/$3/
  3380.         or syntax_error "alias definition";
  3381.         my $alias = $1;
  3382.         my $key = $2;
  3383.         if ($method == $replace_method
  3384.         || $method == $override_method
  3385.         || ($method == $augment_method
  3386.             && ! defined $keycodes_table{$alias})) {
  3387.         $keycodes_table{$alias} = [];
  3388.         $aliases{$alias} = $key;
  3389.         }
  3390.         next;
  3391.     }
  3392.     last;
  3393.     }
  3394.     $method = $oldmethod;
  3395. }
  3396.  
  3397. # Fill @{$symbols_table{$code}[$group]} with symbols
  3398. sub symbols_for_group {
  3399.     my $code = shift;
  3400.     my $group = shift;
  3401.     if ($method == $replace_method
  3402.     || ($method == $override_method
  3403.         && (@_ || ! defined $symbols_table{$code}[$group]))
  3404.     || ($method == $augment_method &&
  3405.         ! defined $symbols_table{$code})) {
  3406.     my $level = 0;
  3407.     for my $symbol (@_) {
  3408.         if ($symbol !~ /\(/ && $symbol =~ /./
  3409.         && (! defined $xkbsym_table{$symbol}
  3410.             || $xkbsym_table{$symbol} ne 'NoSymbol'
  3411.             || ! defined $symbols_table{$code}[$group][$level])) {
  3412.         $symbols_table{$code}[$group][$level] = $symbol;
  3413.         }
  3414.         $level++;
  3415.     }
  3416.     }
  3417. }
  3418.  
  3419. sub xkb_key {
  3420.     my $default_key_type = $_[0];
  3421.     if ($stream =~ /^key</i) {
  3422.     $stream =~ s/^key<([^>]+)>\{([^\}]*?)\};(.*)/$3/i
  3423.         or syntax_error "key definition";
  3424.     my $key = $1;
  3425.     my $list = $2 .",";
  3426.     if ($verbosity >= 4 && ! defined $keycodes_table{$key}) {
  3427.         warning "No scan code for <$key> is defined.\n";
  3428.     }
  3429.     for my $code (@{$keycodes_table{$key}}) {
  3430.         if ($method == $replace_method) {
  3431.         $symbols_table{$code} = [];
  3432.         }
  3433.         my $group = $base_group;
  3434.         while ($list =~ /[^ ]/) {
  3435.         # [ X1, X2, ... ]
  3436.         if ($list =~ s/^\[([^\]]*?)\],(.*)/$2/) {
  3437.             (my $symbols = $1) =~ s/,/ /g;
  3438.             my @groupsymbols = split ' ', $symbols;
  3439.             symbols_for_group $code, $group, @groupsymbols;
  3440.             $group++;
  3441.             next;
  3442.         }
  3443.         # symbols[GroupN] = [ X1, X2, ... ]
  3444.         if ($list =~ (s/^symbols\[Group([1-4])\]
  3445.                   =\[([^\]]*?)\],(.*)/$3/x)) {
  3446.             my $group = $1 - 1 + $base_group;
  3447.             (my $symbols = $2) =~ s/,/ /g;
  3448.             my @groupsymbols = split ' ', $symbols;
  3449.             symbols_for_group $code, $group, @groupsymbols;
  3450.             next;
  3451.         }
  3452.         # type = "...."
  3453.         if ($list =~ (s/^type(?:\[Group1\])?
  3454.                               =\"([^\"]+)\",(.*)/$2/x)) {
  3455.             if ($method == $replace_method
  3456.             || $method == $override_method
  3457.             || ($method == $augment_method
  3458.                 && ! defined $types_table{$code})) {
  3459.             $types_table{$code} = $1;
  3460.             }
  3461.             next;
  3462.         }
  3463.                 # virtualMods = AltGr
  3464.                 # overlay1=<KO7>
  3465.         next if ($list =~ s/^[a-zA-Z0-9_]+(=[a-zA-Z0-9_<>]+)?,
  3466.                                    (.*)/$2/x);
  3467.         # type = "CTRL+ALT"
  3468.         next if ($list =~ s/^[a-zA-Z0-9_]+=\"[^\"]+\",(.*)/$1/);
  3469.         # type[...] = "..."
  3470.         next if ($list =~ s/^type\[[a-zA-Z0-9_]+\]=\"[^\"]+\",
  3471.                                     (.*)/$1/x);
  3472.         # actions[...] = [ ... ]
  3473.         next if ($list =~ s/^actions\[[a-zA-Z0-9_]+\]=\[[^\]]*?\],
  3474.                                     (.*)/$1/x);
  3475.         die "$0: garbage in a key definition: \"$list\""
  3476.             ." in $filename.\n";
  3477.         }
  3478.         if (! defined $types_table{$code}
  3479.         || $types_table{$code} eq 'DEFAULT') {
  3480.         $types_table{$code} = $default_key_type;
  3481.         }
  3482.     }
  3483.     return 1;
  3484.     } else {
  3485.     return 0;
  3486.     }
  3487. }
  3488.  
  3489. sub xkb_symbols_definitions {
  3490.     my $oldmethod = $method;
  3491.     my $default_key_type = 'DEFAULT';
  3492.     while ($stream) {
  3493.     $method = $oldmethod;
  3494.  
  3495.     if (xkb_include ('symbols')) {
  3496.         next;
  3497.     }
  3498.  
  3499.     $method = xkb_method ();
  3500.  
  3501.     if ($stream =~ /^name/i) {
  3502.         $stream =~ s/^name\[[a-zA-Z0-9_]+\]=\"[^\"]*\";(.*)/$1/i
  3503.         or syntax_error "group name";
  3504.         next;
  3505.     }
  3506.  
  3507.     if ($stream =~ (s/^key\.type(?:\[Group1\])?=\"([^\"]+)\";(.*)/$2/)) {
  3508.         $default_key_type = $1;
  3509.         next;
  3510.     }
  3511.     
  3512.     if ($stream =~ s/^[a-zA-Z0-9_]+\.[a-zA-Z0-9_]+=.*?;(.*)/$1/i) {
  3513.         next;
  3514.     }
  3515.  
  3516.     if ($stream =~ s/^[a-zA-Z0-9_]+\.[a-zA-Z0-9_]+\[[a-zA-Z0-9_]+\]
  3517.                        =.*?;(.*)/$1/ix) {
  3518.         next;
  3519.     }
  3520.  
  3521.     if (xkb_key $default_key_type) {
  3522.         next;
  3523.     }
  3524.  
  3525.     if ($stream =~ /^(modifier_map|modmap|mod_map)/i) {
  3526.         $stream =~ (s/^(modifier_map|modmap|mod_map)\s?[a-zA-Z0-9_]+
  3527.             \{[^\}]*\};(.*)/$2/ix)
  3528.         or syntax_error "modifier_map";
  3529.         next;
  3530.     }
  3531.  
  3532.     if ($stream =~ /^virtual_modifiers/i) {
  3533.         $stream =~ (s/^virtual_modifiers\s?[a-zA-Z0-9_,]+;(.*)/$1/ix)
  3534.         or syntax_error "virtual_modifiers";
  3535.         next;
  3536.     }
  3537.     last;
  3538.     }
  3539.     $method = $oldmethod;
  3540. }
  3541.  
  3542. sub xkb_definitions {
  3543.     my $file_type = $_[0];
  3544.     if ($file_type eq 'symbols') {
  3545.     xkb_symbols_definitions();
  3546.     } elsif ($file_type eq 'keycodes') {
  3547.     xkb_keycodes_definitions();
  3548.     } else {
  3549.     die "$0: Bad xkb file type $file_type\n";
  3550.     }
  3551. }
  3552.  
  3553. # Remove from $stream the characters up to the first unmatched "}"
  3554. sub skip_to_brace {
  3555.     while ($stream && ($stream =~ s/^[^\}\{]*\{//)) {
  3556.     &skip_to_brace;
  3557.     }
  3558.     $stream =~ s/^[^\}\{]*(\}|$)//;
  3559. }
  3560.  
  3561. sub xkb_block_list {
  3562.     my $file_type = $_[0];
  3563.     my $block = $_[1];
  3564.     my $first = 1;
  3565.     my $ok = 0;
  3566.     my $mystream = $stream;
  3567.     while ($stream) {
  3568.     my $default = xkb_flags();
  3569.     xkb_identifier() eq "xkb_". $file_type
  3570.         or syntax_error "xkb_". $file_type;
  3571.     my $name = xkb_string();
  3572.     my $structured;
  3573.     if ($stream =~ s/^\{//) {
  3574.         $structured = 1;
  3575.     } else {
  3576.         $structured = 0;
  3577.     }
  3578.     if ($name eq $block || ($first && ! $block)) {
  3579.         xkb_definitions ($file_type);
  3580.         if ($structured) {
  3581.         $stream =~ s/^\};.*// or syntax_error "};";
  3582.         } else {
  3583.         $stream = '';
  3584.         }
  3585.         $ok = 1;
  3586.     } else {
  3587.         if ($structured) {
  3588.         skip_to_brace;
  3589.         $stream =~ s/^;// or syntax_error ";";
  3590.         } else {
  3591.         last;
  3592.         }
  3593.     }
  3594.     $first = 0;
  3595.     }
  3596.     if (! $ok) {
  3597.     $stream = $mystream;
  3598.     }
  3599.     return $ok;
  3600. }
  3601.  
  3602. sub include_xkb_file {
  3603.     my $file_type = $_[0];
  3604.     my $include_list = '^'. $_[1];
  3605.  
  3606.     my $oldmethod = $method;
  3607.     my $oldbase_group = $base_group;
  3608.     while ($include_list) {
  3609.     my $file;
  3610.     my $block;
  3611.     if ($include_list =~ (s/^(\^|\+|\|)([^\(\|\+]+)\(([^\)]+)\)
  3612.                   :([1234])(.*)/$5/x)) {
  3613.         if ($1 eq '+') {
  3614.         $method = $override_method;
  3615.         } elsif ($1 eq '|') {
  3616.         $method = $augment_method;
  3617.         }
  3618.         $file = $2;
  3619.         $block = $3;
  3620.         $base_group = $4 - 1 + $base_group;
  3621.     } elsif ($include_list =~ (s/^(\^|\+|\|)([^\(\|\+]+)\(([^\)]+)\)
  3622.                    (.*)/$4/x)) {
  3623.         if ($1 eq '+') {
  3624.         $method = $override_method;
  3625.         } elsif ($1 eq '|') {
  3626.         $method = $augment_method;
  3627.         }
  3628.         $file = $2;
  3629.         $block = $3;
  3630.     } elsif ($include_list =~ s/^(\^|\+|\|)([^\(\|\+]+):([1234])(.*)/$4/) {
  3631.         if ($1 eq '+') {
  3632.         $method = $override_method;
  3633.         } elsif ($1 eq '|') {
  3634.         $method = $augment_method;
  3635.         }
  3636.         $file = $2;
  3637.         $block = '';
  3638.         $base_group = $3 - 1 + $base_group;
  3639.     } elsif ($include_list =~ s/^(\^|\+|\|)([^\(\|\+]+)(.*)/$3/) {
  3640.         if ($1 eq '+') {
  3641.         $method = $override_method;
  3642.         } elsif ($1 eq '|') {
  3643.         $method = $augment_method;
  3644.         }
  3645.         $file = $2;
  3646.         $block = '';
  3647.     } else {
  3648.         die "$0: bad include list $include_list.\n";
  3649.     }
  3650.     
  3651.     my $oldstream = $stream;
  3652.     if ($file =~ /^\.?\//) {
  3653.         $stream = file_to_string ("$file");
  3654.     } else {
  3655.         $stream = file_to_string (xfilename "$file_type/$file");
  3656.     }
  3657.     my $oldfilename = $filename;
  3658.     $filename = $file;
  3659.     if (!xkb_block_list ($file_type, $block)) {
  3660.         warning "Can not find \"$block\" in \"$file\".\n";
  3661.         xkb_block_list ($file_type, '');
  3662.     }
  3663.     $stream = $oldstream;
  3664.     $filename = $oldfilename;
  3665.     $method = $oldmethod;
  3666.     $base_group = $oldbase_group;
  3667.     }
  3668. }
  3669.  
  3670. include_xkb_file 'keycodes', $keycodes;
  3671.  
  3672. foreach my $alias (keys %aliases) {
  3673.     if (! defined $keycodes_table{$aliases{$alias}}) {
  3674.     die "$0: undefined keyname $aliases{$alias} in ".
  3675.         "an keycode alias definition in $filename.\n";
  3676.     }
  3677.     $keycodes_table{$alias} = [ @{$keycodes_table{$alias}},
  3678.                 @{$keycodes_table{$aliases{$alias}}} ];
  3679. }
  3680.  
  3681. include_xkb_file 'symbols', $symbols;
  3682.  
  3683. if ($arch eq 'at' || $arch eq 'evdev') {
  3684. # Pause - 110, Break - 114, PrintScreen - 111, SysRq - 92
  3685.     for my $group (0 .. 3) {
  3686.         # no separate Break key on AT keyboards.  Break = Ctrl+Pause
  3687.         if (defined $symbols_table{110}[$group][1]) {
  3688.             $symbols_table{114}[$group] = [$symbols_table{110}[$group][1]];
  3689.         }
  3690.         # no separate SysRq key on AT keyboards.  SysRq = Alt+PrintScreen
  3691.         if (defined $symbols_table{111}[$group][1]) {
  3692.             $symbols_table{92}[$group] = [$symbols_table{111}[$group][1]];
  3693.         }
  3694.     }
  3695. }
  3696.  
  3697. foreach my $key (keys %symbols_table) {
  3698.     foreach my $group (0 .. $#{$symbols_table{$key}}) {
  3699.     if (! defined $symbols_table{$key}[$group]) {
  3700.         $symbols_table{$key}[$group] = [];
  3701.     } else {
  3702.         foreach my $level (0 .. $#{$symbols_table{$key}[$group]}) {
  3703.         if (! defined $symbols_table{$key}[$group][$level]) {
  3704.             $symbols_table{$key}[$group][$level] = 'NoSymbol';
  3705.         }
  3706.         }
  3707.     }
  3708.     }
  3709.     if (! defined $types_table{$key}) {
  3710.     $types_table{$key} = 'DEFAULT';
  3711.     }
  3712. }
  3713.  
  3714. sub uni_to_legacy {
  3715.     my $uni = $_[0];
  3716.     if ($acm) {
  3717.     if ($uni <= 0x7f) {
  3718.             if ($freebsd && $uni >= 0x20 && $uni <= 0x7e) {
  3719.                 return sprintf "\'%c\'", $uni;
  3720.             } else {
  3721.                 return sprintf "0x%02x", $uni;
  3722.             }
  3723.     } elsif (defined $acmtable{$uni}) {
  3724.             if ($freebsd) {
  3725.                 return sprintf "%i", $acmtable{$uni};
  3726.             } else {
  3727.                 return sprintf "0x%02x", $acmtable{$uni};
  3728.             }
  3729.     } else {
  3730.         if ($verbosity >= 8) {
  3731.         warning sprintf ("Unicode U+%04x does not exist "
  3732.                  ."in the legacy encoding\n", $uni);
  3733.         }
  3734.         return $voidsymbol;
  3735.     }
  3736.     } else {
  3737.     return 'U+'. sprintf ("%04x", $uni);
  3738.     }
  3739. }
  3740.  
  3741. sub x_to_kernelsym {
  3742.     my $xkeysym = $_[0];
  3743.     my $kernelkeysym = $xkbsym_table{$xkeysym};
  3744.     if (defined $kernelkeysym) {
  3745.         if ($kernelkeysym !~ /^[0-9][0-9a-fA-F]{3}$/) {
  3746.         return $kernelkeysym;
  3747.     }
  3748.     } else {
  3749.     $kernelkeysym = ($xkeysym =~ /^0x0*(100)?([0-9a-fA-F]{4})$/
  3750.              ? $2
  3751.              : ($xkeysym =~ /^U([0-9a-fA-F]+)$/
  3752.                 ? $1 
  3753.                 : undef));
  3754.     }
  3755.     if (defined $kernelkeysym) {
  3756.     my $uni = hex ($kernelkeysym);
  3757.     if (defined $forbidden{$uni}) {
  3758.             if ($verbosity >= 8) {
  3759.                 warning "Forbidden Unicode \"U+$kernelkeysym\"\n";
  3760.             }
  3761.         return $voidsymbol;
  3762.     } else {
  3763.         if (pack("U", $uni) =~ /\p{IsAlpha}/) {
  3764.         my $legacy = uni_to_legacy ($uni);
  3765.         if ($legacy ne $voidsymbol) {
  3766.             return '+'. $legacy; # further processed for FreeBSD
  3767.         } else {
  3768.             return $legacy;
  3769.         }
  3770.         } elsif ($uni <= 0x1f) {
  3771.         return $controlsyms[$uni];
  3772.         } else {
  3773.         return uni_to_legacy ($uni);
  3774.         }
  3775.     }
  3776.     } else {
  3777.     warning "Unknown X keysym \"$xkeysym\"\n";
  3778.     return $voidsymbol;
  3779.     }
  3780. }
  3781.  
  3782. sub x_to_ascii {
  3783.     my $xkeysym = $_[0];
  3784.     my $kernelkeysym = $xkbsym_table{$xkeysym};
  3785.     if (defined $kernelkeysym) {
  3786.         if (defined $controlsyms_hash{$kernelkeysym}) {
  3787.             return $controlsyms_hash{$kernelkeysym};
  3788.     } elsif ($kernelkeysym !~ /^[0-9][0-9a-fA-F]{3}$/) {
  3789.         return undef;
  3790.     }
  3791.     } else {
  3792.     $kernelkeysym = ($xkeysym =~ /^0x0*(100)?([0-9a-fA-F]{4})$/
  3793.              ? $2
  3794.              : ($xkeysym =~ /^U([0-9a-fA-F]+)$/
  3795.                 ? $1 
  3796.                 : undef));
  3797.     }
  3798.     if (defined $kernelkeysym) {
  3799.     my $uni = hex ($kernelkeysym);
  3800.     if (0x00 <= $uni && 0x7f >= $uni) {
  3801.         return $uni;
  3802.     }
  3803.     }
  3804.     return undef;
  3805. }
  3806.  
  3807. # A vector of symbol codes for a key
  3808. my @vector;
  3809. # $numlockable[group] -> whether the group is numlockable
  3810. my @numlockable;
  3811. # A vector with same length as @vector.  Measures how well each element of
  3812. # @vector represents the xkb symbol for the particular key.  Bigger values
  3813. # mean lower quality.
  3814. my @quality;
  3815.  
  3816. sub approximate {
  3817.     my ($coord, $new_sym, $new_quality) = @_;
  3818.     # $new_sym represents the xkb symbol for position $coord in @vector
  3819.     # with quality $new_quality
  3820.     if ((! defined $quality[$coord] || $quality[$coord] > $new_quality)
  3821.     && $new_sym ne $voidsymbol) {
  3822.     $vector[$coord] = $new_sym;
  3823.     $quality[$coord] = $new_quality;
  3824.     }
  3825. }
  3826.  
  3827. # Fill @vector with data for key number $_[0]
  3828. sub flatten {
  3829.     #    Kernel         X
  3830.     # -----------------------------------------
  3831.     # 1  Shift          level 2 (Shift)
  3832.     # 2  AltGr          levels 3 and 4 (AltGr)
  3833.     # 4  Control        Control
  3834.     # 8  Alt            Alt
  3835.     # 0                 Group1
  3836.     # 16 ShiftL         Group2
  3837.     # 32 ShiftR         Group4
  3838.     # 48 ShiftL+ShiftR  Group3
  3839.     my $key = $_[0];
  3840.     @vector = ();
  3841.     @quality = ();
  3842.     @numlockable = (0,0,0,0);
  3843.     my @real_group_table = ([-1, -1, -1, -1],
  3844.                 [0, 0, 0, 0], # gr1 -> gr1 -> gr1 -> gr1
  3845.                 [0, 1, 1, 0], # gr1 -> gr2 -> gr1 -> gr2
  3846.                 [0, 1, 2, 0], # gr1 -> gr2 -> gr1 -> gr3
  3847.                 [0, 1, 3, 2]);# gr1 -> gr2 -> gr3 -> gr4
  3848.     for my $group (0..3) {
  3849.     my $real_group = $real_group_table[1+$#{$symbols_table{$key}}][$group];
  3850.         my $last_level;
  3851.         while ($real_group >= 0
  3852.                && ($last_level = $#{$symbols_table{$key}[$real_group]}) < 0) {
  3853.             $real_group = $real_group - 1;
  3854.         }
  3855.     next if ($real_group < 0);
  3856.     for my $level (0..3) {
  3857.         my $real_level = $level;
  3858.         if ($types_table{$key} eq 'ONE_LEVEL') {
  3859.         $real_level = 0;
  3860.         } elsif ($types_table{$key} eq 'TWO_LEVEL') {
  3861.                 $real_level = $real_level % 2;
  3862.         } elsif ($types_table{$key} eq 'THREE_LEVEL') {
  3863.         if ($real_level > 2) {
  3864.             $real_level = 2;
  3865.         }
  3866.         }
  3867.             if ($last_level == -1) {
  3868.                 next;
  3869.             } elsif ($last_level == 0) {
  3870.                 $real_level = 0;
  3871.             } elsif ($last_level == 1) {
  3872.                 $real_level = $real_level % 2;
  3873.             } elsif ($last_level == 2 && $real_level == 3) {
  3874.                 $real_level = 2;
  3875.             } elsif ($real_level > $last_level) {
  3876.                 $real_level = $last_level;
  3877.             }
  3878.         my $coord;
  3879.         for ($types_table{$key}) {
  3880.         if (/^(DEFAULT|ONE_LEVEL|TWO_LEVEL
  3881.                       |THREE_LEVEL|ALPHABETIC
  3882.                       |EIGHT_LEVEL|EIGHT_LEVEL_ALPHABETIC
  3883.                       |EIGHT_LEVEL_SEMIALPHABETIC
  3884.                       |FOUR_LEVEL|FOUR_LEVEL_ALPHABETIC
  3885.                       |FOUR_LEVEL_SEMIALPHABETIC
  3886.                       |SEPARATE_CAPS_AND_SHIFT_ALPHABETIC
  3887.               |KEYPAD|FOUR_LEVEL_X|FOUR_LEVEL_MIXED_KEYPAD
  3888.               |FOUR_LEVEL_KEYPAD|LOCAL_EIGHT_LEVEL
  3889.                       |FOUR_LEVEL_PLUS_LOCK
  3890.                       )$/x) {
  3891.             # Level0: plain
  3892.             # Level1: shift
  3893.             # Level2: altgr
  3894.             # Level3: shift+altgr
  3895.             $coord = ($group << 4) + $level;
  3896.         } elsif (/^(PC_BREAK|PC_CONTROL_LEVEL2
  3897.                            |PC_LCONTROL_LEVEL2|PC_RCONTROL_LEVEL2)$/x) {
  3898.             # Level0: plain
  3899.             # Level1: control
  3900.             if ($level == 0 || $level == 2) {
  3901.             $coord = ($group << 4) + $level;
  3902.             } else {
  3903.             $coord = ($group << 4) + $level + 3;
  3904.             }
  3905.         } elsif (/^(PC_SYSRQ|PC_ALT_LEVEL2
  3906.                            |PC_LALT_LEVEL2|PC_RALT_LEVEL2)$/x) {
  3907.             # Level0: plain
  3908.             # Level1: alt
  3909.             if ($level == 0 || $level == 2) {
  3910.             $coord = ($group << 4) + $level;
  3911.             } else {
  3912.             # notice that $level is 1 or 3
  3913.             $coord = ($group << 4) + $level + 7;
  3914.             }
  3915.         } elsif (/^SHIFT\+ALT$/) {
  3916.             # Level0: plain
  3917.             # Level1: shift+alt
  3918.             if ($level == 0 || $level == 2) {
  3919.             $coord = ($group << 4) + $level;
  3920.             } else {
  3921.             $coord = ($group << 4) + $level + 8;
  3922.             }
  3923.         } elsif (/^CTRL\+ALT$/) {
  3924.             # Level0: plain
  3925.             # Level1: control+alt
  3926.             if ($level == 0 || $level == 2) {
  3927.             $coord = ($group << 4) + $level;
  3928.             } else {
  3929.             $coord = ($group << 4) + $level + 11;
  3930.             }
  3931.         } else {
  3932.             warning "Unknown key type $types_table{$key}\n";
  3933.             $coord = ($group << 4) + $level;
  3934.         }
  3935.         }
  3936.         my $xkeysym = $symbols_table{$key}[$real_group][$real_level];
  3937.         if ($xkeysym =~ /^KP_/) {
  3938.                 $numlockable[$group] = 1;
  3939.         }
  3940.         my $is_special = ($xkeysym !~ /^U[0-9a-fA-F]+$/
  3941.                   && defined $xkbsym_table{$xkeysym}
  3942.                   && ($xkbsym_table{$xkeysym}
  3943.                   !~ /^[0-9][0-9a-fA-F]{3}$/));
  3944.         my $kernelkeysym = x_to_kernelsym ($xkeysym);
  3945.         approximate ($coord, $kernelkeysym, 0);
  3946.             if (defined (my $ascii = x_to_ascii ($xkeysym))) {
  3947.                 approximate (($coord | 0x08), $metasyms[$ascii], 1);
  3948.                 approximate (($coord | 0x04), $controlsyms[$ascii], 1);
  3949.                 approximate (($coord | 0x0c), $metacontrolsyms[$ascii], 1);
  3950.             } elsif ($is_special) { # this includes being 'NoSymbol'
  3951.                 approximate (($coord | 0x08), $kernelkeysym, 2);
  3952.                 approximate (($coord | 0x04), $kernelkeysym, 2);
  3953.                 approximate (($coord | 0x0c), $kernelkeysym, 2);
  3954.             }
  3955.     }
  3956.     }
  3957.     for my $x (0..1) {
  3958.         my $mask = 1 << $x;
  3959.         for my $coord (0..63) {
  3960.             next if (! defined $vector[$coord]);
  3961.             approximate($coord ^ $mask, $vector[$coord],
  3962.                         $quality[$coord] + $mask << 2);
  3963.         }
  3964.     }
  3965.     for my $coord (0..16) {
  3966.         next if (! defined $vector[$coord]);
  3967.         for my $x (1..3) {
  3968.             my $mask = $x << 4;
  3969.             approximate($coord | $mask, $vector[$coord],
  3970.                         $quality[$coord] + 1 << 6);
  3971.         }
  3972.     }
  3973.     for my $coord (0 .. 63) {
  3974.     if (! defined $vector[$coord]) {
  3975.         $vector[$coord] = $voidsymbol;
  3976.     }
  3977.     }
  3978.  
  3979.     for my $coord (0 .. 63) {
  3980.     next if ($coord & 0x0c); # next if Control and/or Alt
  3981.     my $mask = $kernel_modifiers{$vector[$coord]};
  3982.     next unless (defined $mask);
  3983.     for my $mod (4, 8, 12) {
  3984.         if ($vector[$coord + $mod] eq $voidsymbol
  3985.         && ($vector[($coord + $mod) ^ $mask] eq $voidsymbol)) {
  3986.         $vector[$coord + $mod] = $vector[$coord];
  3987.         }
  3988.     }
  3989.     }
  3990.     
  3991.     # Without this it would be possible to lock permanently
  3992.     # a modifier key such as Control or Alt
  3993.     for my $coord (0 .. 63) {
  3994.     my $mask = $kernel_modifiers{$vector[$coord]};
  3995.     if (defined $mask) {
  3996.         $vector[$coord ^ $mask] = $vector[$coord];
  3997.         if ($compact && ! $freebsd) {
  3998.                 # In non-Latin layouts AltGr=ShiftL
  3999.         # AltGr = 0x02,  ShiftL = 0x10
  4000.         if (($mask & 0x02) && ($mask & 0x10)) {
  4001.             $vector[$coord ^ $mask ^ 0x02] = $vector[$coord];
  4002.             $vector[$coord ^ $mask ^ 0x10] = $vector[$coord];
  4003.         } elsif ($mask & 0x02) {
  4004.             $vector[$coord ^ $mask ^ 0x10] = $vector[$coord];
  4005.             $vector[$coord ^ $mask ^ 0x10 ^ 0x02] = $vector[$coord];
  4006.         } elsif ($mask & 0x10) {
  4007.             $vector[$coord ^ $mask ^ 0x02] = $vector[$coord];
  4008.             $vector[$coord ^ $mask ^ 0x02 ^ 0x10] = $vector[$coord];
  4009.         }
  4010.         }
  4011.     }
  4012.     }
  4013.     
  4014.     if ($freebsd || ! $compact) {
  4015.     for my $coord (16 .. 63) {
  4016.         if ($vector[$coord] =~ /^(ShiftL|ShiftL_Lock|ashift|alock)$/) {
  4017.         $vector[$coord] = $voidsymbol;
  4018.         }
  4019.     }
  4020.     for my $coord (0 .. 15) {
  4021.         if ($vector[$coord] eq 'ShiftL_Lock') {   #  0 => 16
  4022.         $vector[$coord + 16] = 'ShiftR_Lock'; # 16 => 48
  4023.         $vector[$coord + 32] = 'ShiftR_Lock'; # 32 => 0
  4024.         $vector[$coord + 48] = 'ShiftL_Lock'; # 48 => 32
  4025.         } elsif ($vector[$coord] =~ /^(ShiftL|ashift|alock)$/) {
  4026.         $vector[$coord + 16] = $vector[$coord];
  4027.         $vector[$coord + 32] = $vector[$coord];
  4028.         $vector[$coord + 48] = $vector[$coord];
  4029.         }
  4030.     }
  4031.     } else {
  4032.     for my $coord (16 .. 63) {
  4033.         if ($vector[$coord] =~ /^(AltGr|AltGr_Lock)$/) {
  4034.         $vector[$coord] = $voidsymbol;
  4035.         }
  4036.     }
  4037.     for my $coord (0 .. 15) {
  4038.             if ($vector[$coord] =~ /^(AltGr_Lock|AltGr)$/) {
  4039.         $vector[$coord + 16] = $vector[$coord];
  4040.         $vector[$coord + 32] = $vector[$coord];
  4041.         $vector[$coord + 48] = $vector[$coord];
  4042.         }
  4043.     }
  4044.     }
  4045.  
  4046.     for my $group (0 .. 3) {
  4047.     my $kp = undef;
  4048.     for my $x (0 .. 15) {
  4049.         my $coord = 16 * $group + $x;
  4050.         if ($vector[$coord] =~ /^KP_/) {
  4051.         $kp = $vector[$coord];
  4052.         last;
  4053.         }
  4054.     }
  4055.     if ($types_table{$key} =~ /^(KEYPAD|FOUR_LEVEL_X
  4056.                                     |FOUR_LEVEL_MIXED_KEYPAD
  4057.                             |FOUR_LEVEL_KEYPAD)$/x
  4058.         && ! defined $kp) {
  4059.         $kp = 'VoidSymbol';
  4060.             $numlockable[$group] = 1;
  4061.     }
  4062.     if ($kp && ! $freebsd) {
  4063.         for my $x (0 .. 15) {
  4064.         my $coord = 16 * $group + $x;
  4065.         for ($vector[$coord]) {
  4066.             if (/^VoidSymbol$/) {
  4067.             # KP_Begin and KP_Delete are mapped to VoidSymbol
  4068.             $vector[$coord] = $kp;
  4069.             } elsif (/$xkbsym_table{'plus'}/) {# not anchored match!
  4070.             $vector[$coord] = 'KP_Add';
  4071.             } elsif (/$xkbsym_table{'minus'}/) {
  4072.             $vector[$coord] = 'KP_Subtract';
  4073.             } elsif (/$xkbsym_table{'asterisk'}/) {
  4074.             $vector[$coord] = 'KP_Multiply';
  4075.             } elsif (/$xkbsym_table{'slash'}/) {
  4076.             $vector[$coord] = 'KP_Divide';
  4077.             } elsif (/$xkbsym_table{'comma'}/) {
  4078.             $vector[$coord] = 'KP_Comma';
  4079.             } elsif (/$xkbsym_table{'period'}/) {
  4080.             $vector[$coord] = 'KP_Period';
  4081.             } elsif (/$xkbsym_table{'0'}/) {
  4082.             $vector[$coord] = 'KP_0';
  4083.             } elsif (/$xkbsym_table{'1'}/) {
  4084.             $vector[$coord] = 'KP_1';
  4085.             } elsif (/$xkbsym_table{'2'}/) {
  4086.             $vector[$coord] = 'KP_2';
  4087.             } elsif (/$xkbsym_table{'3'}/) {
  4088.             $vector[$coord] = 'KP_3';
  4089.             } elsif (/$xkbsym_table{'4'}/) {
  4090.             $vector[$coord] = 'KP_4';
  4091.             } elsif (/$xkbsym_table{'5'}/) {
  4092.             $vector[$coord] = 'KP_5';
  4093.             } elsif (/$xkbsym_table{'6'}/) {
  4094.             $vector[$coord] = 'KP_6';
  4095.             } elsif (/$xkbsym_table{'7'}/) {
  4096.             $vector[$coord] = 'KP_7';
  4097.             } elsif (/$xkbsym_table{'8'}/) {
  4098.             $vector[$coord] = 'KP_8';
  4099.             } elsif (/$xkbsym_table{'9'}/) {
  4100.             $vector[$coord] = 'KP_9';
  4101.             } elsif (/^(Return|Enter)$/) {
  4102.             $vector[$coord] = 'KP_Enter';
  4103.             } elsif (/^Home$/) {
  4104.             $vector[$coord] = 'KP_7';
  4105.             } elsif (/^Left$/) {
  4106.             $vector[$coord] = 'KP_4';
  4107.             } elsif (/^Up$/) {
  4108.             $vector[$coord] = 'KP_8';
  4109.             } elsif (/^Right$/) {
  4110.             $vector[$coord] = 'KP_6';
  4111.             } elsif (/^Down$/) {
  4112.             $vector[$coord] = 'KP_2';
  4113.             } elsif (/^Prior$/) {
  4114.             $vector[$coord] = 'KP_9';
  4115.             } elsif (/^Next$/) {
  4116.             $vector[$coord] = 'KP_3';
  4117.             } elsif (/^End$/) {
  4118.             $vector[$coord] = 'KP_1';
  4119.             } elsif (/^Insert$/) {
  4120.             $vector[$coord] = 'KP_0';
  4121.             }
  4122.         }
  4123.         }
  4124.     }
  4125.     }
  4126.  
  4127.     for my $group (0 .. 3) {
  4128.     my $coord = $group << 4;
  4129.     my $mainsym = $vector[$coord];
  4130.     if ($mainsym =~ /^fkey([0-9]+)$/) {
  4131.         my $num = $1;
  4132.             if (1 <= $num && $num <= 12) {
  4133.                 $vector[$coord + 1] = 'fkey'. ($num+12); # shift
  4134.                 $vector[$coord + 4] = 'fkey'. ($num+24); # control
  4135.                 $vector[$coord + 5] = 'fkey'. ($num+36); # control + shift
  4136.                 $vector[$coord + 2] = 'scr'. sprintf("%02i", $num); #altgr
  4137.                 my $x = sprintf("%02i", ($num <= 6) ? $num+10 : $num);
  4138.                 $vector[$coord + 3] = 'scr'. $x; # altgr + shift
  4139.                 $vector[$coord + 6] = 'scr'. sprintf("%02i", $num); # altgr+ctrl
  4140.                 $vector[$coord + 7] = 'scr'. $x; # altgr + control + shift
  4141.             } elsif ($num == 52 || $num == 56) {
  4142.                 my $sym = $num == 52 ? '\'-\'' : '\'+\'';
  4143.                 for my $i ($coord .. $coord+15) {
  4144.                     if ($vector[$i] eq $mainsym && $vector[$i^1] eq $mainsym) {
  4145.                         $vector[$i | 1] = $sym;
  4146.                     }
  4147.                 }
  4148.             } elsif ($num == 60 && $vector[$coord + 1] eq 'fkey60') {
  4149.                 $vector[$coord + 1] = 'paste';
  4150.             }
  4151.         } elsif ($mainsym =~ /^esc$/) {
  4152.             $vector[$coord + 6] = 'debug';
  4153.             $vector[$coord + 7] = 'debug';
  4154.         } elsif ($mainsym =~ /^saver$/) { # 'Pause' key
  4155.             $vector[$coord] = 'slock';
  4156.             $vector[$coord + 1] = 'saver'; # shift
  4157.             $vector[$coord + 2] = 'susp';  # altgr
  4158.             $vector[$coord + 3] = 'susp';  # altgr + shift
  4159.             $vector[$coord + 4] = 'slock'; # ctrl
  4160.             $vector[$coord + 5] = 'saver'; # ctrl + shift
  4161.             $vector[$coord + 6] = 'susp';  # ctrl + altgr
  4162.             $vector[$coord + 7] = 'susp';  # ctrl + altgr + shift
  4163.         } elsif ($freebsd && $mainsym =~ /^\' \'$/) {
  4164.             $vector[$coord + 6] = 'susp';
  4165.             $vector[$coord + 7] = 'susp';
  4166.         } elsif ($mainsym =~ /^ht$/) {
  4167.             for my $i ($coord .. $coord+15) {
  4168.                 if ($vector[$i] eq 'ht' && $vector[$i ^ 1] eq 'ht') {
  4169.                     $vector[$i | 1] = 'btab';
  4170.                 }
  4171.             }
  4172.         } elsif ($mainsym =~ /^nscr$/) {
  4173.             for my $i ($coord .. $coord+15) {
  4174.                 if ($vector[$i] eq 'nscr' && $vector[$i ^ 1] eq 'nscr') {
  4175.                     $vector[$i | 1] = 'pscr';
  4176.                 }
  4177.             }
  4178.             $vector[$coord + 4] = 'debug';
  4179.             $vector[$coord + 5] = 'debug';
  4180.     } elsif ($mainsym =~ /^F([0-9]+)$/) {
  4181.         my $num = $1;
  4182.         $vector[$coord + 1] = 'F'. ($num + 12); # shift
  4183.         $vector[$coord + 2] = 'Console_'. ($num + 12); # altgr
  4184.         $vector[$coord + 3] = 'Console_'. ($num + 24); # altgr + shift
  4185.         $vector[$coord + 4] = 'F'. ($num + 24); # control
  4186.         $vector[$coord + 5] = 'F'. ($num + 36); # control + shift
  4187.         $vector[$coord + 6] = 'Console_'. ($num + 12); # control + altgr
  4188.         $vector[$coord + 7] = 'Console_'. ($num + 24); # control+altgr+shift
  4189.         $vector[$coord + 8] = 'Console_'. $num; # alt
  4190.         $vector[$coord + 9] = 'Console_'. ($num + 12); # alt + shift
  4191.         $vector[$coord + 12] = 'Console_'. $num; # control + alt
  4192.         $vector[$coord + 13] = 'Console_'. ($num + 12); # control+alt+shift
  4193.     } elsif ($mainsym eq 'Scroll_Lock' || $mainsym eq 'Help') {
  4194.         $vector[$coord + 1] = 'Show_Memory';
  4195.         $vector[$coord + 2] = 'Show_Registers';
  4196.         $vector[$coord + 4] = 'Show_State';
  4197.         $vector[$coord + 8] = 'Show_Registers';
  4198.     } elsif ($mainsym =~ /^KP_([0-9])$/) {
  4199.         my $num = $1;
  4200.         $vector[$coord + 2] = 'Hex_'. $num;
  4201.         $vector[$coord + 9] = 'Hex_'. $num;
  4202.         $vector[$coord + 8] = 'Ascii_'. $num;
  4203.     } elsif ($mainsym eq 'Num_Lock') {
  4204.         $vector[$coord + 2] = 'Hex_A';
  4205.         $vector[$coord + 9] = 'Hex_A';
  4206.     } elsif ($mainsym eq 'KP_Divide') {
  4207.         $vector[$coord + 2] = 'Hex_B';
  4208.         $vector[$coord + 9] = 'Hex_B';
  4209.     } elsif ($mainsym eq 'KP_Multiply') {
  4210.         $vector[$coord + 2] = 'Hex_C';
  4211.         $vector[$coord + 9] = 'Hex_C';
  4212.     } elsif ($mainsym eq 'KP_Subtract') {
  4213.         $vector[$coord + 2] = 'Hex_D';
  4214.         $vector[$coord + 9] = 'Hex_D';
  4215.     } elsif ($mainsym eq 'KP_Add') {
  4216.         $vector[$coord + 2] = 'Hex_E';
  4217.         $vector[$coord + 9] = 'Hex_E';
  4218.     } elsif ($mainsym eq 'KP_Enter') {
  4219.         $vector[$coord + 2] = 'Hex_F';
  4220.         $vector[$coord + 9] = 'Hex_F';
  4221.     } elsif ($mainsym eq 'Prior' || $mainsym eq 'PageUp') {
  4222.         $vector[$coord + 1] = 'Scroll_Backward';
  4223.     } elsif ($mainsym eq 'Next' || $mainsym eq 'PageDown') {
  4224.         $vector[$coord + 1] = 'Scroll_Forward';
  4225.     } elsif ($mainsym eq 'Left') {
  4226.         $vector[$coord + 8] = 'Decr_Console';
  4227.     } elsif ($mainsym eq 'Right') {
  4228.         $vector[$coord + 8] = 'Incr_Console';
  4229.     } elsif ($mainsym eq 'Up') {
  4230.         $vector[$coord + 8] = 'KeyboardSignal';
  4231.     }
  4232.     }
  4233.     return @vector;
  4234. }
  4235.  
  4236. sub print_vector {
  4237.     my $kernel_code = $_[0];
  4238.     my $only_VoidSymbol = 1;
  4239.     my $no_NoSymbol = 1;
  4240.     for my $mask (0 .. 63) {
  4241.     if ($vector[$mask] ne $voidsymbol && $vector[$mask] ne 'NoSymbol') {
  4242.         $only_VoidSymbol = 0;
  4243.         last;
  4244.     }
  4245.     }
  4246.     return if ($only_VoidSymbol && $compact);
  4247.     for my $mask (0 .. 63) {
  4248.     if ($vector[$mask] eq 'NoSymbol') {
  4249.         $no_NoSymbol = 0;
  4250.         last;
  4251.     }
  4252.     }
  4253.     if ($freebsd) {
  4254.         my @capslockable = (0,0,0,0);
  4255.     for my $group (0 .. 3) {
  4256.         if ($vector[$group * 16] =~ /^\+/) {
  4257.                 $capslockable[$group] = 1;
  4258.                 last;
  4259.             }
  4260.         }
  4261.     for my $mask (0 .. 63) {
  4262.         $vector[$mask] =~ s/^\+//;
  4263.         $vector[$mask] =~ s/^NoSymbol$/nop/;
  4264.         }
  4265.         for my $group (0 .. 1) {
  4266.             next if ($group && $symbols !~ /:2/);
  4267.             my $lockstate = ($capslockable[$group] ? 
  4268.                              ($numlockable[$group] ? 'B' : 'C')
  4269.                              : ($numlockable[$group] ? 'N' : 'O'));
  4270.             $KEYMAP .= sprintf "  %03i   ", $kernel_code + 128*$group;
  4271.             for my $mask (0, 1, 4, 5, 2, 3, 6, 7) {
  4272.                 $KEYMAP .= sprintf "%-6s ", $vector[$mask + 16*$group];
  4273.             }
  4274.             $KEYMAP .= " $lockstate\n";
  4275.         }
  4276.     } elsif ($compact) {
  4277.     my $line = ($symbols =~ /:2/ # true if the keymap is non-latin
  4278.             ? "@vector[0, 1, 16, 17, 4, 20, 8, 24, 12, 28]"
  4279.             : "@vector[0, 1, 2, 3, 4, 6, 8, 10, 12, 14]");
  4280.     $line =~ s/NoSymbol/VoidSymbol/g;
  4281.     $KEYMAP .= "keycode $kernel_code = $line\n";
  4282.     } else {
  4283.     my @capsvector = @vector;
  4284.     for my $mask (0 .. 63) {
  4285.         if ($capsvector[$mask] =~ /^(\+?)U\+([0-9a-fA-F]+)$/) {
  4286.         my $v = hex ($2);
  4287.         my $l = ord (lc (pack ("U", $v)));
  4288.         my $u = ord (uc (pack ("U", $v)));
  4289.         my $c = ($v == $l ? $u : $l);
  4290.         $capsvector[$mask] = $1 ."U+". sprintf ("%04x", $c);
  4291.         if ($v != $c && $v gt 0x7f) {
  4292.             $broken_caps = 1;
  4293.         }
  4294.         }
  4295.     }
  4296.     if ($no_NoSymbol) {
  4297.         $KEYMAP .= "keycode $kernel_code = @vector @capsvector\n";
  4298.     } else {
  4299.         for my $mask (0 .. 63) {
  4300.         if ($vector[$mask] ne 'NoSymbol') {
  4301.             $KEYMAP .= "$modifier_combinations[$mask]"
  4302.             ." keycode $kernel_code = $vector[$mask]\n";
  4303.             if ($modifier_combinations[$mask] =~ /plain/) {
  4304.             $KEYMAP .= "ctrll"
  4305.                 ." keycode $kernel_code = $capsvector[$mask]\n";
  4306.             } else {
  4307.             $KEYMAP .= "ctrll $modifier_combinations[$mask]"
  4308.                 ." keycode $kernel_code = $capsvector[$mask]\n";
  4309.             }
  4310.         }
  4311.         }
  4312.     }
  4313.     }
  4314. }
  4315.  
  4316. my %at_scancodes = (
  4317.     9 => 1,
  4318.     10 => 2,
  4319.     11 => 3,
  4320.     12 => 4,
  4321.     13 => 5,
  4322.     14 => 6,
  4323.     15 => 7,
  4324.     16 => 8,
  4325.     17 => 9,
  4326.     18 => 10,
  4327.     19 => 11,
  4328.     20 => 12,
  4329.     21 => 13,
  4330.     22 => 14,
  4331.     23 => 15,
  4332.     24 => 16,
  4333.     25 => 17,
  4334.     26 => 18,
  4335.     27 => 19,
  4336.     28 => 20,
  4337.     29 => 21,
  4338.     30 => 22,
  4339.     31 => 23,
  4340.     32 => 24,
  4341.     33 => 25,
  4342.     34 => 26,
  4343.     35 => 27,
  4344.     36 => 28,
  4345.     37 => 29,
  4346.     38 => 30,
  4347.     39 => 31,
  4348.     40 => 32,
  4349.     41 => 33,
  4350.     42 => 34,
  4351.     43 => 35,
  4352.     44 => 36,
  4353.     45 => 37,
  4354.     46 => 38,
  4355.     47 => 39,
  4356.     48 => 40,
  4357.     49 => 41,
  4358.     50 => 42,
  4359.     51 => 43,
  4360.     52 => 44,
  4361.     53 => 45,
  4362.     54 => 46,
  4363.     55 => 47,
  4364.     56 => 48,
  4365.     57 => 49,
  4366.     58 => 50,
  4367.     59 => 51,
  4368.     60 => 52,
  4369.     61 => 53,
  4370.     62 => 54,
  4371.     63 => 55,
  4372.     64 => 56,
  4373.     65 => 57,
  4374.     66 => 58,
  4375.     67 => 59,
  4376.     68 => 60,
  4377.     69 => 61,
  4378.     70 => 62,
  4379.     71 => 63,
  4380.     72 => 64,
  4381.     73 => 65,
  4382.     74 => 66,
  4383.     75 => 67,
  4384.     76 => 68,
  4385.     77 => 69,
  4386.     78 => 70,
  4387.     79 => 71,
  4388.     80 => 72,
  4389.     81 => 73,
  4390.     82 => 74,
  4391.     83 => 75,
  4392.     84 => 76,
  4393.     85 => 77,
  4394.     86 => 78,
  4395.     87 => 79,
  4396.     88 => 80,
  4397.     89 => 81,
  4398.     90 => 82,
  4399.     91 => 83,
  4400.     92 => 84,
  4401.     93 => -1, # fake key (KP_Equal)
  4402.     94 => 86,
  4403.     95 => 87,
  4404.     96 => 88,
  4405.     97 => 102,
  4406.     98 => 103,
  4407.     99 => 104,
  4408.     100 => 105,
  4409.     102 => 106,
  4410.     103 => 107,
  4411.     104 => 108,
  4412.     105 => 109,
  4413.     106 => 110,
  4414.     107 => 111,
  4415.     108 => 96,
  4416.     109 => 97,
  4417.     110 => 119,
  4418.     111 => 99,
  4419.     112 => 98,
  4420.     113 => 100,
  4421.     114 => 101,
  4422.     115 => 125,
  4423.     116 => 126,
  4424.     117 => 127,
  4425.     118 => -1,  # Japanese
  4426.     119 => -1,  # Japanese
  4427.     120 => -1,  # Japanese
  4428.     123 => -1,
  4429.     124 => -1,  # fake key
  4430.     125 => -1,  # fake key
  4431.     126 => -1,  # fake key
  4432.     127 => -1,  # fake key
  4433.     128 => -1,  # fake key
  4434.     129 => -1,  # Japanese
  4435.     131 => -1,  # Japanese
  4436.     133 => 124, # Japanese
  4437.     134 => 121, # Brasilian ABNT2
  4438.     144 => -1,  # Japanese
  4439.     156 => -1,  # fake key
  4440.     208 => -1,  # Japanese
  4441.     209 => -1,  # Korean
  4442.     210 => -1,  # Korean
  4443.     211 => 89,  # Brasilian ABNT2, Japanese
  4444.     214 => -1,  # alternate between internal and multimedia display
  4445.     215 => -1,  # turn light on/of
  4446.     216 => -1,  # brightness down
  4447.     217 => -1,  # brightness up
  4448. );
  4449.  
  4450. my %freebsd_scancodes = (
  4451.     9 => 1,
  4452.     10 => 2,
  4453.     11 => 3,
  4454.     12 => 4,
  4455.     13 => 5,
  4456.     14 => 6,
  4457.     15 => 7,
  4458.     16 => 8,
  4459.     17 => 9,
  4460.     18 => 10,
  4461.     19 => 11,
  4462.     20 => 12,
  4463.     21 => 13,
  4464.     22 => 14,
  4465.     23 => 15,
  4466.     24 => 16,
  4467.     25 => 17,
  4468.     26 => 18,
  4469.     27 => 19,
  4470.     28 => 20,
  4471.     29 => 21,
  4472.     30 => 22,
  4473.     31 => 23,
  4474.     32 => 24,
  4475.     33 => 25,
  4476.     34 => 26,
  4477.     35 => 27,
  4478.     36 => 28,
  4479.     37 => 29,
  4480.     38 => 30,
  4481.     39 => 31,
  4482.     40 => 32,
  4483.     41 => 33,
  4484.     42 => 34,
  4485.     43 => 35,
  4486.     44 => 36,
  4487.     45 => 37,
  4488.     46 => 38,
  4489.     47 => 39,
  4490.     48 => 40,
  4491.     49 => 41,
  4492.     50 => 42,
  4493.     51 => 43,
  4494.     52 => 44,
  4495.     53 => 45,
  4496.     54 => 46,
  4497.     55 => 47,
  4498.     56 => 48,
  4499.     57 => 49,
  4500.     58 => 50,
  4501.     59 => 51,
  4502.     60 => 52,
  4503.     61 => 53,
  4504.     62 => 54,
  4505.     63 => 55,
  4506.     64 => 56,
  4507.     65 => 57,
  4508.     66 => 58,
  4509.     67 => 59,
  4510.     68 => 60,
  4511.     69 => 61,
  4512.     70 => 62,
  4513.     71 => 63,
  4514.     72 => 64,
  4515.     73 => 65,
  4516.     74 => 66,
  4517.     75 => 67,
  4518.     76 => 68,
  4519.     77 => 69,
  4520.     78 => 70,
  4521.     79 => 71,
  4522.     80 => 72,
  4523.     81 => 73,
  4524.     82 => 74,
  4525.     83 => 75,
  4526.     84 => 76,
  4527.     85 => 77,
  4528.     86 => 78,
  4529.     87 => 79,
  4530.     88 => 80,
  4531.     89 => 81,
  4532.     90 => 82,
  4533.     91 => 83,
  4534.     92 => 84,
  4535.     93 => -1, # fake key (KP_Equal)
  4536.     94 => 86,
  4537.     95 => 87,
  4538.     96 => 88,
  4539.     97 => 94,
  4540.     98 => 95,
  4541.     99 => 96,
  4542.     100 => 97,
  4543.     102 => 98,
  4544.     103 => 99,
  4545.     104 => 100,
  4546.     105 => 101,
  4547.     106 => 102,
  4548.     107 => 103,
  4549.     108 => 89,
  4550.     109 => 90,
  4551.     110 => 104,
  4552.     111 => 92,
  4553.     112 => 91,
  4554.     113 => 93,
  4555.     114 => 108,
  4556.     115 => 105,
  4557.     116 => 106,
  4558.     117 => 107,
  4559.     118 => -1,  # Japanese
  4560.     119 => -1,  # Japanese
  4561.     120 => -1,  # Japanese
  4562.     123 => -1,
  4563.     124 => -1,  # fake key
  4564.     125 => -1,  # fake key
  4565.     126 => -1,  # fake key
  4566.     127 => -1,  # fake key
  4567.     128 => -1,  # fake key
  4568.     129 => -1,  # Japanese
  4569.     131 => -1,  # Japanese
  4570.     133 => 125, # Japanese
  4571.     134 => 126, # Brasilian ABNT2
  4572.     144 => -1,  # Japanese
  4573.     156 => -1,  # fake key
  4574.     208 => -1,  # Japanese
  4575.     209 => -1,  # Korean
  4576.     210 => -1,  # Korean
  4577.     211 => 115,  # Brasilian ABNT2, Japanese
  4578.     214 => -1,  # alternate between internal and multimedia display
  4579.     215 => -1,  # turn light on/of
  4580.     216 => -1,  # brightness down
  4581.     217 => -1,  # brightness up
  4582. );
  4583.  
  4584. if ($freebsd) {
  4585.     $KEYMAP .= 
  4586. "#                                                         alt\n".
  4587. "# scan                       cntrl          alt    alt   cntrl lock\n".
  4588. "# code  base   shift  cntrl  shift  alt    shift  cntrl  shift state\n".
  4589. "# ------------------------------------------------------------------\n";
  4590. #"  000   nop    nop    nop    nop    nop    nop    nop    nop     O\n";
  4591. } elsif ($compact) {
  4592.     $KEYMAP .= "keymaps 0-4,6,8,10,12,14\n";
  4593. } else {
  4594.     $KEYMAP .= "keymaps 0-127\n";
  4595. }
  4596.  
  4597. if ($freebsd) {
  4598.     foreach my $key (sort {$a <=> $b} (keys %symbols_table)) {
  4599.     my $kernel_code = $freebsd_scancodes{$key};
  4600.     next if (! defined $kernel_code || $kernel_code < 0);
  4601.     @vector = flatten ($key);
  4602.     if ($kernel_code == 83 || $kernel_code == 103) {
  4603.         for my $coord (0+6, 0+7, 16+6, 16+7, 32+6, 32+7, 48+6, 48+7,) {
  4604.         $vector[$coord] = 'boot';
  4605.         }
  4606.         }
  4607.     print_vector $kernel_code;
  4608.     }
  4609. } elsif ($arch eq 'at' || $arch eq 'evdev') {
  4610.     foreach my $key (sort {$a <=> $b} (keys %symbols_table)) {
  4611.     my $kernel_code = (($arch eq 'at') ? $at_scancodes{$key} : $key - 8);
  4612.     next if (! defined $kernel_code || $kernel_code < 0);
  4613.         @vector = flatten ($key);
  4614.         if ($kernel_code == 99) {
  4615.         for my $coord (0, 1, 16, 17, 32, 33, 48, 49) {
  4616.         $vector[$coord] = 'VoidSymbol';
  4617.         }
  4618.      } elsif ($kernel_code == 83 || $kernel_code == 111) {
  4619.         for my $coord (0+6, 0+12, 0+14, 
  4620.                            16+6, 16+12, 16+14,
  4621.                            32+6, 32+12, 32+14, 
  4622.                            48+6, 48+12, 48+14) {
  4623.         $vector[$coord] = 'Boot';
  4624.         }
  4625.     }
  4626.     print_vector $kernel_code;
  4627.     }
  4628. } elsif ($arch eq 'macintosh') {
  4629.     foreach my $key (sort {$a <=> $b} (keys %symbols_table)) {
  4630.     my $kernel_code = $key - 8;
  4631.     @vector = flatten ($key);
  4632.     print_vector $kernel_code;
  4633.     }
  4634.     $KEYMAP .= '\
  4635. keycode 127 =
  4636.         shift   control keycode 127 = Boot
  4637. '
  4638. } elsif ($arch eq 'ataritt') {
  4639.     foreach my $key (sort {$a <=> $b} (keys %symbols_table)) {
  4640.     my $kernel_code = $key - 8;
  4641.     if ($kernel_code == 97) {
  4642.         @vector = ('F246', 'Break', 'F246', 'F246',
  4643.                'F246', 'F246', 'F246', 'F246', 
  4644.                'Last_Console', 'F246', 'F246', 'F246', 
  4645.                'F246', 'F246', 'F246', 'F246') x 4;
  4646.     } else {
  4647.         @vector = flatten ($key);
  4648.     }
  4649.     if ($kernel_code == 83 || $kernel_code == 113) {
  4650.         for my $coord (0+6, 0+12, 0+14, 
  4651.                            16+6, 16+12, 16+14,
  4652.                            32+6, 32+12, 32+14, 
  4653.                            48+6, 48+12, 48+14) {
  4654.         $vector[$coord] = 'Boot';
  4655.         }
  4656.     }
  4657.     print_vector $kernel_code;
  4658.     }
  4659. } elsif ($arch eq 'amiga') {
  4660.     foreach my $key (sort {$a <=> $b} (keys %symbols_table)) {
  4661.     my $kernel_code = $key - 8;
  4662.     @vector = flatten ($key);
  4663.     if ($kernel_code == 60) {
  4664.         for my $coord (0+6, 0+12, 0+14, 
  4665.                            16+6, 16+12, 16+14,
  4666.                            32+6, 32+12, 32+14, 
  4667.                            48+6, 48+12, 48+14) {
  4668.         $vector[$coord] = 'Boot';
  4669.         }
  4670.     }
  4671.     print_vector $kernel_code;
  4672.     }
  4673. } elsif ($arch eq 'sun') {
  4674.     foreach my $key (sort {$a <=> $b} (keys %symbols_table)) {
  4675.     my $kernel_code = $key - 7;
  4676.     @vector = flatten ($key);
  4677.     if ($kernel_code == 50) {
  4678.         for my $coord (0+6, 0+12, 0+14, 
  4679.                            16+6, 16+12, 16+14,
  4680.                            32+6, 32+12, 32+14, 
  4681.                            48+6, 48+12, 48+14) {
  4682.         $vector[$coord] = 'Boot';
  4683.         }
  4684.     }
  4685.     print_vector $kernel_code;
  4686.     }
  4687. } else {
  4688.     die "$0: Unsupported keyboard type $arch\n";
  4689. }
  4690.  
  4691. if ($broken_caps) {
  4692.     $KEYMAP =~ s/Caps_Lock/CtrlL_Lock/g;
  4693. }
  4694.  
  4695. print $KEYMAP;
  4696.  
  4697. if ($freebsd) {
  4698.     if ($charmap) {
  4699.         my $file1 = "/etc/console-setup/dkey.${charmap}.inc";
  4700.         my $file2 = "$installdir/etc/console-setup/dkey.${charmap}.inc";
  4701.         if (-f $file1) {
  4702.             system("cat $file1");
  4703.         } elsif (-f $file2) {
  4704.             system("cat $file2");
  4705.         }
  4706.     }
  4707. } else {
  4708.     print "strings as usual\n";
  4709.  
  4710.     if ($charmap) {
  4711.         my $file1 = "/etc/console-setup/compose.${charmap}.inc";
  4712.         my $file2 = "$installdir/etc/console-setup/compose.${charmap}.inc";
  4713.         if (-f $file1) {
  4714.             system("cat $file1");
  4715.         } elsif (-f $file2) {
  4716.             system("cat $file2");
  4717.         }
  4718.     }
  4719. }
  4720. my $file1 = "/etc/console-setup/remap.inc";
  4721. my $file2 = "$installdir/etc/console-setup/remap.inc";
  4722. if (-f $file1) {
  4723.     system("cat $file1");
  4724. } elsif (-f $file2) {
  4725.     system("cat $file2");
  4726. }
  4727.  
  4728. exit 0;
  4729.